Merge pull request #104 from YunoHost/regen-conf

Major update: Add a configuration file generator
This commit is contained in:
Jérôme Lebleu 2015-10-03 03:29:06 +02:00
commit ef7234ce20
90 changed files with 5998 additions and 613 deletions

View file

@ -243,6 +243,10 @@ domain:
authenticate: all
authenticator: ldap-anonymous
arguments:
-r:
full: --raw
help: Return domains as a bash-usable list instead of JSON
action: store_true
-f:
full: --filter
help: LDAP filter used to search
@ -260,6 +264,7 @@ domain:
action_help: Create a custom domain
api: POST /domains
configuration:
lock: false
authenticate: all
arguments:
domain:
@ -278,6 +283,7 @@ domain:
action_help: Delete domains
api: DELETE /domains/<domain>
configuration:
lock: false
authenticate: all
arguments:
domain:
@ -913,6 +919,63 @@ service:
default: 50
type: int
### service_regenconf()
regenconf:
action_help: >
Regenerate the configuration file(s) for a service and compare the result
with the existing configuration file.
Prints the differences between files if any.
api: PUT /services/regenconf
configuration:
lock: false
arguments:
-s:
full: --service
help: Regenerate configuration for a specfic service
-f:
full: --force
help: Override the current configuration with the newly generated one, even if it has been modified
action: store_true
### service_safecopy()
safecopy:
action_help: >
Check if the specific file has been modified and display differences.
Stores the file hash in the services.yml file
api: PUT /services/safecopy
arguments:
new_conf_file:
help: Path to the desired conf file
conf_file:
help: Path to the targeted conf file
-s:
full: --service
help: Service name attached to the conf file
extra:
required: True
-f:
full: --force
help: Override the current configuration with the newly generated one, even if it has been modified
action: store_true
### service_saferemove()
saferemove:
action_help: >
Check if the specific file has been modified before removing it.
Backup the file in /home/yunohost.backup
api: PUT /services/safecopy
arguments:
conf_file:
help: Path to the targeted conf file
-s:
full: --service
help: Service name attached to the conf file
extra:
required: True
-f:
full: --force
help: Force file deletion
action: store_true
#############################
# Firewall #

View file

@ -0,0 +1,26 @@
#!/bin/bash
set -e
force=$1
cd /usr/share/yunohost/templates/yunohost
sudo mkdir -p /etc/yunohost
if [ ! -f /etc/yunohost/current_host ]; then
echo "yunohost.org" | sudo tee /etc/yunohost/current_host
fi
if [ ! -f /etc/yunohost/firewall.yml ]; then
sudo cp firewall.yml /etc/yunohost/firewall.yml
fi
if [ ! -f /etc/yunohost/services.yml ]; then
sudo cp services.yml /etc/yunohost/services.yml
fi
# Allow users to access /media directory
if [ ! -d /etc/skel/media ]; then
mkdir -p /media
ln -s /media /etc/skel/
fi

View file

@ -0,0 +1,65 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [ $force ]; then
sudo yunohost service safecopy \
-s ssl $1 $2 --force
else
sudo yunohost service safecopy \
-s ssl $1 $2
fi
fi
}
cd /usr/share/yunohost/templates/ssl
ssl_dir=/usr/share/yunohost/yunohost-config/ssl/yunoCA
sudo mkdir -p /etc/yunohost/certs/yunohost.org
sudo mkdir -p $ssl_dir/{ca,certs,crl,newcerts}
safe_copy openssl.cnf $ssl_dir/openssl.cnf
[ -f $ssl_dir/serial ] \
|| (echo "00" | sudo tee $ssl_dir/serial)
[ -f $ssl_dir/index.txt ] \
|| sudo touch $ssl_dir/index.txt
if [ ! -f /etc/yunohost/certs/yunohost.org/ca.pem ]; then
sudo openssl req -x509 -new -config $ssl_dir/openssl.cnf \
-days 3650 -out $ssl_dir/ca/cacert.pem \
-keyout $ssl_dir/ca/cakey.pem -nodes -batch
sudo cp $ssl_dir/ca/cacert.pem \
/etc/yunohost/certs/yunohost.org/ca.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/ca.pem \
/etc/ssl/certs/ca-yunohost_crt.pem
sudo update-ca-certificates
fi
if [ ! -f /etc/yunohost/certs/yunohost.org/crt.pem ]; then
sudo openssl req -new -config $ssl_dir/openssl.cnf \
-days 730 -out $ssl_dir/certs/yunohost_csr.pem \
-keyout $ssl_dir/certs/yunohost_key.pem -nodes -batch
sudo openssl ca -config $ssl_dir/openssl.cnf \
-days 730 -in $ssl_dir/certs/yunohost_csr.pem \
-out $ssl_dir/certs/yunohost_crt.pem -batch
last_cert=$(ls $ssl_dir/newcerts/*.pem | sort -V | tail -n 1)
sudo chmod 640 $ssl_dir/certs/yunohost_key.pem
sudo chmod 640 $last_cert
sudo cp $ssl_dir/certs/yunohost_key.pem \
/etc/yunohost/certs/yunohost.org/key.pem
sudo cp $last_cert \
/etc/yunohost/certs/yunohost.org/crt.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/crt.pem \
/etc/ssl/certs/yunohost_crt.pem
sudo ln -sf /etc/yunohost/certs/yunohost.org/key.pem \
/etc/ssl/private/yunohost_key.pem
fi

View file

@ -0,0 +1,31 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [ $force ]; then
sudo yunohost service safecopy \
-s ssh \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s ssh \
$1 $2
fi
}
cd /usr/share/yunohost/templates/ssh
# Only overwrite SSH configuration on an ISO installation
if [ ! -f /etc/yunohost/from_script ]; then
# Do not listen to IPv6 if unavailable
if [ ! -f /proc/net/if_inet6 ]; then
sudo sed -i "s/ListenAddress ::/#ListenAddress ::/g" sshd_config
fi
safe_copy sshd_config /etc/ssh/sshd_config
sudo service ssh restart
fi

View file

@ -0,0 +1,52 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s slapd $1 $2 --force
else
sudo yunohost service safecopy \
-s slapd $1 $2
fi
fi
}
cd /usr/share/yunohost/templates/slapd
# Remove legacy configuration file
[ ! -f /etc/yunohost/installed ] \
|| sudo yunohost service saferemove -s slapd \
/etc/ldap/slapd-yuno.conf
safe_copy sudo.schema /etc/ldap/schema/sudo.schema
safe_copy mailserver.schema /etc/ldap/schema/mailserver.schema
safe_copy ldap.conf /etc/ldap/ldap.conf
safe_copy slapd.default /etc/default/slapd
# Compatibility: change from HDB to MDB on Jessie
version=$(sed 's/\..*//' /etc/debian_version)
if [[ "$version" == '8' ]]; then
cat slapd.conf \
| sed "s/hdb$/mdb/g" \
| sed "s/back_hdb/back_mdb/g" \
| sed "s/^dbconfig set_/#dbconfig set_/g" \
| sudo tee slapd.conf
fi
safe_copy slapd.conf /etc/ldap/slapd.conf
sudo chown root:openldap /etc/ldap/slapd.conf
sudo rm -Rf /etc/ldap/slapd.d
sudo mkdir /etc/ldap/slapd.d
sudo chown -R openldap:openldap /etc/ldap/schema/
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
sudo slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d/
sudo chown -R openldap:openldap /etc/ldap/slapd.d/
sudo service slapd force-reload

View file

@ -0,0 +1,27 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nslcd \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s nslcd \
$1 $2
fi
}
cd /usr/share/yunohost/templates/nslcd
safe_copy nslcd.conf /etc/nslcd.conf
# Fix: Add a blank line at the end of the file
# to avoid nscld restart failure
echo -e "\n" | sudo tee -a /etc/nslcd.conf
sudo service nslcd restart

View file

@ -0,0 +1,80 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s metronome \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s metronome \
$1 $2
fi
}
cd /usr/share/yunohost/templates/metronome
# Copy additional modules
files="ldap.lib.lua
mod_auth_ldap2.lua
mod_legacyauth.lua
mod_storage_ldap.lua
vcard.lib.lua"
for file in $files; do
safe_copy modules/$file /usr/lib/metronome/modules/$file
done
# Copy configuration files
main_domain=$(cat /etc/yunohost/current_host)
cat metronome.cfg.lua.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee metronome.cfg.lua
safe_copy metronome.cfg.lua /etc/metronome/metronome.cfg.lua
safe_copy metronome.init /etc/init.d/metronome
safe_copy metronome.logrotate /etc/logrotate.d/metronome
need_restart=False
sudo mkdir -p /etc/metronome/conf.d
domain_list=$(sudo yunohost domain list --plain)
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')"
sudo mkdir -p /var/lib/metronome/$sanitzed_domain/pep
cat domain.cfg.lua.sed \
| sed "s/{{ domain }}/$domain/g" \
| sudo tee $domain.cfg.lua
if [[ $(safe_copy $domain.cfg.lua /etc/metronome/conf.d/$domain.cfg.lua) == "True" ]]; then
need_restart=True
fi
done
# Remove old domains files
for file in /etc/metronome/conf.d/*; do
domain=$(echo $file \
| sed 's|/etc/metronome/conf.d/||' \
| sed 's|.cfg.lua||')
sanitzed_domain="$(echo $domain | sed 's/\./%2e/g')"
[[ $domain_list =~ $domain ]] \
|| ($(sudo yunohost service saferemove -s metronome $file) == "True" \
&& rm -rf /var/lib/metronome/$sanitzed_domain)
done
# Create domain directory
sudo chown -R metronome: /var/lib/metronome/
sudo chown -R metronome: /etc/metronome/conf.d/
# Restart if need be
if [[ "$need_restart" == "True" ]]; then
sudo service metronome restart
else
sudo service metronome reload
fi

View file

@ -0,0 +1,83 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [ ! -f /etc/yunohost/installed ]; then
sudo cp $1 $2
else
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nginx \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s nginx \
$1 $2
fi
fi
}
cd /usr/share/yunohost/templates/nginx
# Copy plain single configuration files
files="ssowat.conf
yunohost_admin.conf
yunohost_admin.conf.inc
yunohost_api.conf.inc
yunohost_panel.conf.inc"
for file in $files; do
safe_copy $file /etc/nginx/conf.d/$file
done
if [ -f /etc/yunohost/installed ]; then
need_restart=False
domain_list=$(sudo yunohost domain list --plain)
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
sudo mkdir -p /etc/nginx/conf.d/$domain.d
cat server.conf.sed \
| sed "s/{{ domain }}/$domain/g" \
| sudo tee $domain.conf
[[ $(safe_copy $domain.conf /etc/nginx/conf.d/$domain.conf) == "True" ]] \
&& need_restart=True
[ -f /etc/nginx/conf.d/$domain.d/yunohost_local.conf ] \
&& [[ $main_domain != $domain ]] \
&& sudo yunohost service saferemove -s nginx \
/etc/nginx/conf.d/$domain.d/yunohost_local.conf
done
# Copy 'yunohost.local' to the main domain conf directory
main_domain=$(cat /etc/yunohost/current_host)
safe_copy yunohost_local.conf \
/etc/nginx/conf.d/$main_domain.d/yunohost_local.conf
# Remove old domains files
for file in /etc/nginx/conf.d/*.*.conf; do
domain=$(echo $file \
| sed 's|/etc/nginx/conf.d/||' \
| sed 's|.conf||')
[[ $domain_list =~ $domain ]] \
|| ($(sudo yunohost service saferemove -s nginx $file) == "True" \
&& (rm -r /etc/nginx/conf.d/$domain.d || true))
done
else
[ ! -f /etc/nginx/sites-available/default ] \
|| rm -f /etc/nginx/sites-enabled/default
need_restart=True
fi
# Restart if need be
[[ "$need_restart" == "True" ]] \
&& sudo service nginx restart \
|| sudo service nginx reload

View file

@ -0,0 +1,56 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s postfix \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s postfix \
$1 $2
fi
}
cd /usr/share/yunohost/templates/postfix
# Copy plain single configuration files
files="header_check
ldap-accounts.cf
ldap-aliases.cf
ldap-domains.cf
master.cf
sender_canonical
smtp_reply_filter"
for file in $files; do
safe_copy $file /etc/postfix/$file
done
main_domain=$(cat /etc/yunohost/current_host)
# Replace main domain in the main configuration file
cat main.cf.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee main.cf
# And adapt it to IPv4-only hosts
if [ ! -f /proc/net/if_inet6 ]; then
sudo sed -i \
's/ \[::ffff:127.0.0.0\]\/104 \[::1\]\/128//g' \
main.cf
sudo sed -i \
's/inet_interfaces = all/inet_interfaces = all\ninet_protocols = ipv4/' \
main.cf
fi
if [[ $(safe_copy main.cf /etc/postfix/main.cf) == "True" ]]; then
sudo service postfix restart
else
sudo service postfix reload
fi

View file

@ -0,0 +1,23 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s postgrey \
$1 $2 \
--force
else
sudo yunohost service safecopy \
-s postgrey \
$1 $2
fi
}
cd /usr/share/yunohost/templates/postgrey
if [[ "$(safe_copy postgrey.default /etc/default/postgrey)" == "True" ]]; then
sudo service nslcd restart
fi

View file

@ -0,0 +1,54 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s dovecot $1 $2 --force
else
sudo yunohost service safecopy \
-s dovecot $1 $2
fi
}
cd /usr/share/yunohost/templates/dovecot
# Create vmail user
sudo id vmail > /dev/null 2>&1 \
|| sudo adduser --system --ingroup mail --uid 500 vmail
# Replace main domain in the main configuration file
main_domain=$(cat /etc/yunohost/current_host)
cat dovecot.conf.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee dovecot.conf
# Handle IPv4 only systems
if [ ! -f /proc/net/if_inet6 ];
then
sudo sed -i 's/^listen.*/listen = \*/' dovecot.conf
fi
safe_copy dovecot.conf /etc/dovecot/dovecot.conf
safe_copy dovecot-ldap.conf /etc/dovecot/dovecot-ldap.conf
# Setup Sieve
sudo rm -rf /etc/dovecot/global_script
sudo mkdir -p -m 0770 /etc/dovecot/global_script
safe_copy sa-learn-pipe.sh /usr/bin/sa-learn-pipe.sh
sudo chmod 755 /usr/bin/sa-learn-pipe.sh
safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve
sudo chmod 660 /etc/dovecot/global_script/dovecot.sieve > /dev/null 2>&1 \
|| safe_copy dovecot.sieve /etc/dovecot/global_script/dovecot.sieve
sudo sievec /etc/dovecot/global_script/dovecot.sieve
sudo chmod 660 /etc/dovecot/global_script/dovecot.svbin
sudo service dovecot restart

View file

@ -0,0 +1,21 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s spamassassin $1 $2 --force
else
sudo yunohost service safecopy \
-s spamassassin $1 $2
fi
}
cd /usr/share/yunohost/templates/spamassassin
safe_copy spamassassin.default /etc/default/spamassassin
safe_copy local.cf /etc/spamassassin/local.cf
sudo service spamassassin restart

View file

@ -0,0 +1,37 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s amavis $1 $2 --force
else
sudo yunohost service safecopy \
-s amavis $1 $2
fi
}
cd /usr/share/yunohost/templates/amavis
sudo mkdir -p /etc/amavis/conf.d/
# Copy plain single configuration files
files="05-domain_id
05-node_id
15-content_filter_mode
20-debian_defaults"
for file in $files; do
safe_copy $file /etc/amavis/conf.d/$file
done
main_domain=$(cat /etc/yunohost/current_host)
cat 50-user.sed \
| sed "s/{{ main_domain }}/$main_domain/g" \
| sudo tee 50-user
safe_copy 50-user /etc/amavis/conf.d/50-user
sudo service amavis restart

View file

@ -0,0 +1,36 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s mysql $1 $2 --force
else
sudo yunohost service safecopy \
-s mysql $1 $2
fi
}
function randpass () {
[ "$2" == "0" ] && CHAR="[:alnum:]" || CHAR="[:graph:]"
cat /dev/urandom | tr -cd "$CHAR" | head -c ${1:-32}
echo
}
cd /usr/share/yunohost/templates/mysql
if [[ "$(safe_copy my.cnf /etc/mysql/my.cnf)" == "True" ]]; then
sudo service mysql restart
fi
if [ ! -f /etc/yunohost/mysql ]; then
[[ $(/bin/ps aux | grep mysqld | grep -vc "grep") == "0" ]] \
&& sudo service mysql start
mysql_password=$(randpass 10 0)
sudo mysqladmin -u root -pyunohost password $mysql_password
echo $mysql_password | sudo tee /etc/yunohost/mysql
sudo chmod 400 /etc/yunohost/mysql
fi

View file

@ -0,0 +1,20 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s avahi-daemon $1 $2 --force
else
sudo yunohost service safecopy \
-s avahi-daemon $1 $2
fi
}
cd /usr/share/yunohost/templates/avahi-daemon
if [[ "$(safe_copy avahi-daemon.conf /etc/avahi/avahi-daemon.conf)" == "True" ]]; then
sudo service avahi-daemon restart
fi

View file

@ -0,0 +1,20 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s glances $1 $2 --force
else
sudo yunohost service safecopy \
-s glances $1 $2
fi
}
cd /usr/share/yunohost/templates/glances
if [[ "$(safe_copy glances.default /etc/default/glances)" == "True" ]]; then
sudo service glances restart
fi

View file

@ -0,0 +1,50 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s dnsmasq $1 $2 --force
else
sudo yunohost service safecopy \
-s dnsmasq $1 $2
fi
}
cd /usr/share/yunohost/templates/dnsmasq
# Get IP address
ip=$(curl ip.yunohost.org || echo '0.0.0.0')
# Get IPv6 IP address
ipv6=$(ip route get 2000:: | grep -q "unreachable" && echo '' \
|| ip route get 2000:: | grep -v ' fe80:' | grep -v 'cache' | awk '{print $9}')
sudo mkdir -p /etc/dnsmasq.d
domain_list=$(sudo yunohost domain list --plain)
# Copy a configuration file for each YunoHost domain
for domain in $domain_list; do
cat domain.sed \
| sed "s/{{ domain }}/$domain/g" \
| sed "s/{{ ip }}/$ip/g" \
| sudo tee $domain
if [[ "$ipv6" != "" ]]; then
echo "address=/$domain/$ipv6" | sudo tee -a $domain
fi
safe_copy $domain /etc/dnsmasq.d/$domain
done
# Remove old domains files
for file in /etc/dnsmasq.d/*.*; do
domain=$(echo $file | sed 's|/etc/dnsmasq.d/||')
[[ $domain_list =~ $domain ]] \
|| sudo yunohost service saferemove -s dnsmasq $file
done
sudo service dnsmasq reload

View file

@ -0,0 +1,20 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s nsswitch $1 $2 --force
else
sudo yunohost service safecopy \
-s nsswitch $1 $2
fi
}
cd /usr/share/yunohost/templates/nsswitch
if [[ "$(safe_copy nsswitch.conf /etc/nsswitch.conf)" == "True" ]]; then
sudo service nscd restart
fi

View file

@ -0,0 +1,20 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s udisks-glue $1 $2 --force
else
sudo yunohost service safecopy \
-s udisks-glue $1 $2
fi
}
cd /usr/share/yunohost/templates/udisks-glue
if [[ "$(safe_copy udisks-glue.conf /etc/udisks-glue.conf)" == "True" ]]; then
sudo service udisks-glue restart
fi

View file

@ -0,0 +1,29 @@
#!/bin/bash
set -e
force=$1
function safe_copy () {
if [[ "$force" == "True" ]]; then
sudo yunohost service safecopy \
-s fail2ban $1 $2 --force
else
sudo yunohost service safecopy \
-s fail2ban $1 $2
fi
}
cd /usr/share/yunohost/templates/fail2ban
sudo mkdir -p /etc/fail2ban/filter.d
safe_copy yunohost.conf /etc/fail2ban/filter.d/yunohost.conf
# Compatibility: change from HDB to MDB on Jessie
version=$(sed 's/\..*//' /etc/debian_version)
[[ "$version" == '8' ]] \
&& sudo cp jail-jessie.conf jail.conf \
|| sudo cp jail-wheezy.conf jail.conf
if [[ $(safe_copy jail.conf /etc/fail2ban/jail.conf) == "True" ]]; then
sudo service fail2ban restart
fi

View file

@ -0,0 +1,19 @@
use strict;
# $mydomain is used just for convenience in the config files and it is not
# used internally by amavisd-new except in the default X_HEADER_LINE (which
# Debian overrides by default anyway).
#chomp($mydomain = `head -n 1 /etc/mailname`);
# amavisd-new needs to know which email domains are to be considered local
# to the administrative domain. Only emails to "local" domains are subject
# to certain functionality, such as the addition of spam tags.
#
# Default local domains to $mydomain and all subdomains. Remember to
# override or redefine this if $mydomain is changed later in the config
# sequence.
@local_domains_acl = ( ".$mydomain" );
1; # ensure a defined return

View file

@ -0,0 +1,13 @@
use strict;
# $myhostname is used by amavisd-new for node identification, and it is
# important to get it right (e.g. for ESMTP EHLO, loop detection, and so on).
#chomp($myhostname = `hostname --fqdn`);
# To manually set $myhostname, edit the following line with the correct Fully
# Qualified Domain Name (FQDN) and remove the # at the beginning of the line.
#
#$myhostname = "mail.example.com";
1; # ensure a defined return

View file

@ -0,0 +1,23 @@
use strict;
# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.
#
# Default antivirus checking mode
# Uncomment the two lines below to enable it back
#
#@bypass_virus_checks_maps = (
# \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
#
# Default SPAM checking mode
# Uncomment the two lines below to enable it back
#
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
1; # ensure a defined return

View file

@ -0,0 +1,216 @@
use strict;
# ADMINISTRATORS:
# Debian suggests that any changes you need to do that should never
# be "updated" by the Debian package should be made in another file,
# overriding the settings in this file.
#
# The package will *not* overwrite your settings, but by keeping
# them separate, you will make the task of merging changes on these
# configuration files much simpler...
# see /usr/share/doc/amavisd-new/examples/amavisd.conf-default for
# a list of all variables with their defaults;
# see /usr/share/doc/amavisd-new/examples/amavisd.conf-sample for
# a traditional-style commented file
# [note: the above files were not converted to Debian settings!]
#
# for more details see documentation in /usr/share/doc/amavisd-new
# and at http://www.ijs.si/software/amavisd/amavisd-new-docs.html
$QUARANTINEDIR = "$MYHOME/virusmails";
$quarantine_subdir_levels = 1; # enable quarantine dir hashing
$log_recip_templ = undef; # disable by-recipient level-0 log entries
$DO_SYSLOG = 1; # log via syslogd (preferred)
$syslog_ident = 'amavis'; # syslog ident tag, prepended to all messages
$syslog_facility = 'mail';
$syslog_priority = 'debug'; # switch to info to drop debug output, etc
$enable_db = 1; # enable use of BerkeleyDB/libdb (SNMP and nanny)
$enable_global_cache = 1; # enable use of libdb-based cache if $enable_db=1
$inet_socket_port = 10024; # default listening socket
$sa_spam_subject_tag = '***SPAM*** ';
$sa_tag_level_deflt = undef; # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 4.00; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 20.00; # triggers spam evasive actions
$sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent
$sa_mail_body_size_limit = 200*1024; # don't waste time on SA if mail is larger
$sa_local_tests_only = 0; # only tests which do not require internet access?
$recipient_delimiter = '+';
@addr_extension_spam_maps = ('Junk');
# Quota limits to avoid bombs (like 42.zip)
$MAXLEVELS = 14;
$MAXFILES = 1500;
$MIN_EXPANSION_QUOTA = 100*1024; # bytes
$MAX_EXPANSION_QUOTA = 300*1024*1024; # bytes
# You should:
# Use D_DISCARD to discard data (viruses)
# Use D_BOUNCE to generate local bounces by amavisd-new
# Use D_REJECT to generate local or remote bounces by the calling MTA
# Use D_PASS to deliver the message
#
# Whatever you do, *NEVER* use D_REJECT if you have other MTAs *forwarding*
# mail to your account. Use D_BOUNCE instead, otherwise you are delegating
# the bounce work to your friendly forwarders, which might not like it at all.
#
# On dual-MTA setups, one can often D_REJECT, as this just makes your own
# MTA generate the bounce message. Test it first.
#
# Bouncing viruses is stupid, always discard them after you are sure the AV
# is working correctly. Bouncing real SPAM is also useless, if you cannot
# D_REJECT it (and don't D_REJECT mail coming from your forwarders!).
$final_virus_destiny = D_DISCARD; # (data not lost, see virus quarantine)
$final_banned_destiny = D_BOUNCE; # D_REJECT when front-end MTA
$final_spam_destiny = D_DISCARD;
$final_bad_header_destiny = D_PASS; # False-positive prone (for spam)
$enable_dkim_verification = 1; #disabled to prevent warning
$enable_dkim_signing =1;
$virus_admin = "postmaster\@$mydomain"; # due to D_DISCARD default
# Set to empty ("") to add no header
$X_HEADER_LINE = "Debian $myproduct_name at $mydomain";
# REMAINING IMPORTANT VARIABLES ARE LISTED HERE BECAUSE OF LONGER ASSIGNMENTS
#
# DO NOT SEND VIRUS NOTIFICATIONS TO OUTSIDE OF YOUR DOMAIN. EVER.
#
# These days, almost all viruses fake the envelope sender and mail headers.
# Therefore, "virus notifications" became nothing but undesired, aggravating
# SPAM. This holds true even inside one's domain. We disable them all by
# default, except for the EICAR test pattern.
#
@viruses_that_fake_sender_maps = (new_RE(
[qr'\bEICAR\b'i => 0], # av test pattern name
[qr/.*/ => 1], # true for everything else
));
@keep_decoded_original_maps = (new_RE(
# qr'^MAIL$', # retain full original message for virus checking (can be slow)
qr'^MAIL-UNDECIPHERABLE$', # recheck full mail if it contains undecipherables
qr'^(ASCII(?! cpio)|text|uuencoded|xxencoded|binhex)'i,
# qr'^Zip archive data', # don't trust Archive::Zip
));
# for $banned_namepath_re, a new-style of banned table, see amavisd.conf-sample
$banned_filename_re = new_RE(
# qr'^UNDECIPHERABLE$', # is or contains any undecipherable components
# block certain double extensions anywhere in the base name
qr'\.[^./]*\.(exe|vbs|pif|scr|bat|cmd|com|cpl|dll)\.?$'i,
qr'\{[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\}?$'i, # Windows Class ID CLSID, strict
qr'^application/x-msdownload$'i, # block these MIME types
qr'^application/x-msdos-program$'i,
qr'^application/hta$'i,
# qr'^application/x-msmetafile$'i, # Windows Metafile MIME type
# qr'^\.wmf$', # Windows Metafile file(1) type
# qr'^message/partial$'i, qr'^message/external-body$'i, # rfc2046 MIME types
# [ qr'^\.(Z|gz|bz2)$' => 0 ], # allow any in Unix-compressed
# [ qr'^\.(rpm|cpio|tar)$' => 0 ], # allow any in Unix-type archives
# [ qr'^\.(zip|rar|arc|arj|zoo)$'=> 0 ], # allow any within such archives
# [ qr'^application/x-zip-compressed$'i => 0], # allow any within such archives
qr'.\.(exe|vbs|pif|scr|bat|cmd|com|cpl)$'i, # banned extension - basic
# qr'.\.(ade|adp|app|bas|bat|chm|cmd|com|cpl|crt|emf|exe|fxp|grp|hlp|hta|
# inf|ins|isp|js|jse|lnk|mda|mdb|mde|mdw|mdt|mdz|msc|msi|msp|mst|
# ops|pcd|pif|prg|reg|scr|sct|shb|shs|vb|vbe|vbs|
# wmf|wsc|wsf|wsh)$'ix, # banned ext - long
# qr'.\.(mim|b64|bhx|hqx|xxe|uu|uue)$'i, # banned extension - WinZip vulnerab.
qr'^\.(exe-ms)$', # banned file(1) types
# qr'^\.(exe|lha|tnef|cab|dll)$', # banned file(1) types
);
# See http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262631
# and http://www.cknow.com/vtutor/vtextensions.htm
# ENVELOPE SENDER SOFT-WHITELISTING / SOFT-BLACKLISTING
@score_sender_maps = ({ # a by-recipient hash lookup table,
# results from all matching recipient tables are summed
# ## per-recipient personal tables (NOTE: positive: black, negative: white)
# 'user1@example.com' => [{'bla-mobile.press@example.com' => 10.0}],
# 'user3@example.com' => [{'.ebay.com' => -3.0}],
# 'user4@example.com' => [{'cleargreen@cleargreen.com' => -7.0,
# '.cleargreen.com' => -5.0}],
## site-wide opinions about senders (the '.' matches any recipient)
'.' => [ # the _first_ matching sender determines the score boost
new_RE( # regexp-type lookup table, just happens to be all soft-blacklist
[qr'^(bulkmail|offers|cheapbenefits|earnmoney|foryou)@'i => 5.0],
[qr'^(greatcasino|investments|lose_weight_today|market\.alert)@'i=> 5.0],
[qr'^(money2you|MyGreenCard|new\.tld\.registry|opt-out|opt-in)@'i=> 5.0],
[qr'^(optin|saveonlsmoking2002k|specialoffer|specialoffers)@'i => 5.0],
[qr'^(stockalert|stopsnoring|wantsome|workathome|yesitsfree)@'i => 5.0],
[qr'^(your_friend|greatoffers)@'i => 5.0],
[qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i => 5.0],
),
# read_hash("/var/amavis/sender_scores_sitewide"),
# This are some examples for whitelists, since envelope senders can be forged
# they are not enabled by default.
{ # a hash-type lookup table (associative array)
#'nobody@cert.org' => -3.0,
#'cert-advisory@us-cert.gov' => -3.0,
#'owner-alert@iss.net' => -3.0,
#'slashdot@slashdot.org' => -3.0,
#'securityfocus.com' => -3.0,
#'ntbugtraq@listserv.ntbugtraq.com' => -3.0,
#'security-alerts@linuxsecurity.com' => -3.0,
#'mailman-announce-admin@python.org' => -3.0,
#'amavis-user-admin@lists.sourceforge.net'=> -3.0,
#'amavis-user-bounces@lists.sourceforge.net' => -3.0,
#'spamassassin.apache.org' => -3.0,
#'notification-return@lists.sophos.com' => -3.0,
#'owner-postfix-users@postfix.org' => -3.0,
#'owner-postfix-announce@postfix.org' => -3.0,
#'owner-sendmail-announce@lists.sendmail.org' => -3.0,
#'sendmail-announce-request@lists.sendmail.org' => -3.0,
#'donotreply@sendmail.org' => -3.0,
#'ca+envelope@sendmail.org' => -3.0,
#'noreply@freshmeat.net' => -3.0,
#'owner-technews@postel.acm.org' => -3.0,
#'ietf-123-owner@loki.ietf.org' => -3.0,
#'cvs-commits-list-admin@gnome.org' => -3.0,
#'rt-users-admin@lists.fsck.com' => -3.0,
#'clp-request@comp.nus.edu.sg' => -3.0,
#'surveys-errors@lists.nua.ie' => -3.0,
#'emailnews@genomeweb.com' => -5.0,
#'yahoo-dev-null@yahoo-inc.com' => -3.0,
#'returns.groups.yahoo.com' => -3.0,
#'clusternews@linuxnetworx.com' => -3.0,
#lc('lvs-users-admin@LinuxVirtualServer.org') => -3.0,
#lc('owner-textbreakingnews@CNNIMAIL12.CNN.COM') => -5.0,
# soft-blacklisting (positive score)
#'sender@example.net' => 3.0,
#'.example.net' => 1.0,
},
], # end of site-wide tables
});
1; # ensure a defined return

View file

@ -0,0 +1,30 @@
use strict;
#
# Place your configuration directives here. They will override those in
# earlier files.
#
# See /usr/share/doc/amavisd-new/ for documentation and examples of
# the directives you can use in this file
#
$myhostname = "{{ main_domain }}";
$mydomain = "{{ main_domain }}";
# Enable LDAP support
$enable_ldap = 1;
# Default LDAP settings
$default_ldap = {
hostname => "127.0.0.1",
tls => 0,
version => 3,
base => "dc=yunohost,dc=org",
scope => "sub",
query_filter => "(&(objectClass=inetOrgPerson)(mail=%m))",
};
#------------ Do not modify anything below this line -------------
1; # ensure a defined return

View file

@ -0,0 +1,68 @@
# This file is part of avahi.
#
# avahi is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# avahi is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with avahi; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA.
# See avahi-daemon.conf(5) for more information on this configuration
# file!
[server]
host-name=yunohost
domain-name=local
#browse-domains=0pointer.de, zeroconf.org
use-ipv4=yes
use-ipv6=yes
#allow-interfaces=eth0
#deny-interfaces=eth1
#check-response-ttl=no
#use-iff-running=no
#enable-dbus=yes
#disallow-other-stacks=no
#allow-point-to-point=no
#cache-entries-max=4096
#clients-max=4096
#objects-per-client-max=1024
#entries-per-entry-group-max=32
ratelimit-interval-usec=1000000
ratelimit-burst=1000
[wide-area]
enable-wide-area=yes
[publish]
#disable-publishing=no
#disable-user-service-publishing=no
#add-service-cookie=no
#publish-addresses=yes
#publish-hinfo=yes
#publish-workstation=yes
#publish-domain=yes
#publish-dns-servers=192.168.50.1, 192.168.50.2
#publish-resolv-conf-dns-servers=yes
#publish-aaaa-on-ipv4=yes
#publish-a-on-ipv6=no
[reflector]
#enable-reflector=no
#reflect-ipv=no
[rlimits]
#rlimit-as=
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=768
rlimit-stack=4194304
rlimit-nproc=3

View file

@ -0,0 +1,7 @@
resolv-file=
address=/{{ domain }}/{{ ip }}
txt-record={{ domain }},"v=spf1 mx a -all"
mx-host={{ domain }},{{ domain }},5
srv-host=_xmpp-client._tcp.{{ domain }},{{ domain }},5222,0,5
srv-host=_xmpp-server._tcp.{{ domain }},{{ domain }},5269,0,5
srv-host=_jabber._tcp.{{ domain }},{{ domain }},5269,0,5

View file

@ -0,0 +1,9 @@
hosts = 127.0.0.1
auth_bind = yes
ldap_version = 3
base = ou=users,dc=yunohost,dc=org
user_attrs = uidNumber=500,gidNumber=8,mailuserquota=quota_rule=*:bytes=%$
user_filter = (&(objectClass=inetOrgPerson)(uid=%n))
pass_filter = (&(objectClass=inetOrgPerson)(uid=%n))
default_pass_scheme = SSHA

View file

@ -0,0 +1,92 @@
# 2.1.7: /etc/dovecot/dovecot.conf
# OS: Linux 3.2.0-3-686-pae i686 Debian wheezy/sid ext4
listen = *, ::
auth_mechanisms = plain login
login_greeting = Dovecot ready!!
mail_gid = 8
mail_home = /var/mail/%n
mail_location = maildir:/var/mail/%n
mail_uid = 500
passdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
protocols = imap sieve
mail_plugins = $mail_plugins quota
service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0660
user = postfix
}
unix_listener auth-master {
group = mail
mode = 0660
user = vmail
}
}
protocol sieve {
}
ssl_ca = </etc/ssl/certs/ca-yunohost_crt.pem
ssl_cert = </etc/ssl/certs/yunohost_crt.pem
ssl_key = </etc/ssl/private/yunohost_key.pem
ssl_protocols = !SSLv2 !SSLv3
userdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
protocol imap {
imap_client_workarounds =
mail_plugins = $mail_plugins imap_quota antispam autocreate
}
protocol lda {
auth_socket_path = /var/run/dovecot/auth-master
mail_plugins = quota sieve
postmaster_address = postmaster@{{ main_domain }}
}
plugin {
sieve = /var/mail/sievescript/%n/.dovecot.sieve
sieve_dir = /var/mail/sievescript/%n/scripts/
sieve_before = /etc/dovecot/global_script/
}
plugin {
antispam_debug_target = syslog
antispam_verbose_debug = 0
antispam_backend = pipe
antispam_trash = Trash
antispam_spam = SPAM;Junk
antispam_allow_append_to_spam = no
antispam_pipe_program = /usr/bin/sa-learn-pipe.sh
antispam_pipe_program_spam_arg = --spam
antispam_pipe_program_notspam_arg = --ham
}
plugin {
autocreate = Trash
autocreate2 = Junk
autosubscribe = Trash
autosubscribe2 = Junk
}
plugin {
quota = maildir:User quota
quota_rule2 = SPAM:ignore
quota_rule3 = Trash:ignore
}
plugin {
quota_warning = storage=95%% quota-warning 95 %u
quota_warning2 = storage=80%% quota-warning 80 %u
quota_warning3 = -storage=100%% quota-warning below %u # user is no longer over quota
}
service quota-warning {
executable = script /usr/bin/quota-warning.sh
user = vmail
unix_listener quota-warning {
}
}

View file

@ -0,0 +1,4 @@
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
fileinto "Junk";
}

View file

@ -0,0 +1,9 @@
#!/bin/sh
echo /usr/bin/sa-learn $* /tmp/sendmail-msg-$$.txt ;
echo "$$-start ($*)" >> /tmp/sa-learn-pipe.log ;
#echo $* > /tmp/sendmail-parms.txt ;
cat<&0 >> /tmp/sendmail-msg-$$.txt ;
/usr/bin/sa-learn $* /tmp/sendmail-msg-$$.txt ;
rm -f /tmp/sendmail-msg-$$.txt ;
echo "$$-end" >> /tmp/sa-learn-pipe.log ;
exit 0;

View file

@ -0,0 +1,584 @@
# Fail2Ban configuration file.
#
# This file was composed for Debian systems from the original one
# provided now under /usr/share/doc/fail2ban/examples/jail.conf
# for additional examples.
#
# Comments: use '#' for comment lines and ';' for inline comments
#
# To avoid merges during upgrades DO NOT MODIFY THIS FILE
# and rather provide your changes in /etc/fail2ban/jail.local
#
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.
[DEFAULT]
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be
# defined using space separator.
ignoreip = 127.0.0.1/8
# External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise.
#
# ignorecommand = /path/to/command <ip>
ignorecommand =
# "bantime" is the number of seconds that a host is banned.
bantime = 600
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 600
maxretry = 3
# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling" and "auto".
# This option can be overridden in each jail as well.
#
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
# If pyinotify is not installed, Fail2ban will use auto.
# gamin: requires Gamin (a file alteration monitor) to be installed.
# If Gamin is not installed, Fail2ban will use auto.
# polling: uses a polling algorithm which does not require external libraries.
# auto: will try to use the following backends, in order:
# pyinotify, gamin, polling.
backend = auto
# "usedns" specifies if jails should trust hostnames in logs,
# warn when reverse DNS lookups are performed, or ignore all hostnames in logs
#
# yes: if a hostname is encountered, a reverse DNS lookup will be performed.
# warn: if a hostname is encountered, a reverse DNS lookup will be performed,
# but it will be logged as a warning.
# no: if a hostname is encountered, will not be used for banning,
# but it will be logged as info.
usedns = warn
#
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = root@localhost
#
# Name of the sender for mta actions
sendername = Fail2Ban
# Email address of the sender
sender = fail2ban@localhost
#
# ACTIONS
#
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
# email action. Since 0.8.1 upstream fail2ban uses sendmail
# MTA for the mailing. Change mta configuration parameter to mail
# if you want to revert to conventional 'mail'.
mta = sendmail
# Default protocol
protocol = tcp
# Specify chain where jumps would need to be added in iptables-* actions
chain = INPUT
#
# Action shortcuts. To be used to define action parameter
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
#
# JAILS
#
# Next jails corresponds to the standard configuration in Fail2ban 0.6 which
# was shipped in Debian. Enable any defined here jail by including
#
# [SECTION_NAME]
# enabled = true
#
# in /etc/fail2ban/jail.local.
#
# Optionally you may override any other parameter (e.g. banaction,
# action, port, logpath, etc) in that section within jail.local
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
[dropbear]
enabled = false
port = ssh
filter = dropbear
logpath = /var/log/auth.log
maxretry = 6
# Generic filter for pam. Has to be used with action which bans all ports
# such as iptables-allports, shorewall
[pam-generic]
enabled = true
# pam-generic filter can be customized to monitor specific subset of 'tty's
filter = pam-generic
# port actually must be irrelevant but lets leave it all for some possible uses
port = all
banaction = iptables-allports
port = anyport
logpath = /var/log/auth.log
maxretry = 6
[xinetd-fail]
enabled = false
filter = xinetd-fail
port = all
banaction = iptables-multiport-log
logpath = /var/log/daemon.log
maxretry = 2
[ssh-ddos]
enabled = false
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 6
# Here we use blackhole routes for not requiring any additional kernel support
# to store large volumes of banned IPs
[ssh-route]
enabled = false
filter = sshd
action = route
logpath = /var/log/sshd.log
maxretry = 6
# Here we use a combination of Netfilter/Iptables and IPsets
# for storing large volumes of banned IPs
#
# IPset comes in two versions. See ipset -V for which one to use
# requires the ipset package and kernel support.
[ssh-iptables-ipset4]
enabled = false
port = ssh
filter = sshd
banaction = iptables-ipset-proto4
logpath = /var/log/sshd.log
maxretry = 6
[ssh-iptables-ipset6]
enabled = false
port = ssh
filter = sshd
banaction = iptables-ipset-proto6
logpath = /var/log/sshd.log
maxretry = 6
#
# HTTP servers
#
[apache]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
# default action is now multiport, so apache-multiport jail was left
# for compatibility with previous (<0.7.6-2) releases
[apache-multiport]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/apache*/*error.log
maxretry = 2
[apache-modsecurity]
enabled = false
filter = apache-modsecurity
port = http,https
logpath = /var/log/apache*/*error.log
maxretry = 2
[apache-nohome]
enabled = false
filter = apache-nohome
port = http,https
logpath = /var/log/apache*/*error.log
maxretry = 2
# Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year
# of usage in production environments.
[php-url-fopen]
enabled = false
port = http,https
filter = php-url-fopen
logpath = /var/www/*/logs/access_log
# A simple PHP-fastcgi jail which works with lighttpd.
# If you run a lighttpd server, then you probably will
# find these kinds of messages in your error_log:
# ALERT tried to register forbidden variable GLOBALS
# through GET variables (attacker '1.2.3.4', file '/var/www/default/htdocs/index.php')
[lighttpd-fastcgi]
enabled = false
port = http,https
filter = lighttpd-fastcgi
logpath = /var/log/lighttpd/error.log
# Same as above for mod_auth
# It catches wrong authentifications
[lighttpd-auth]
enabled = false
port = http,https
filter = suhosin
logpath = /var/log/lighttpd/error.log
[nginx-http-auth]
enabled = false
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
# Monitor roundcube server
[roundcube-auth]
enabled = false
filter = roundcube-auth
port = http,https
logpath = /var/log/roundcube/userlogins
[sogo-auth]
enabled = false
filter = sogo-auth
port = http, https
# without proxy this would be:
# port = 20000
logpath = /var/log/sogo/sogo.log
#
# FTP servers
#
[vsftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = vsftpd
logpath = /var/log/vsftpd.log
# or overwrite it in jails.local to be
# logpath = /var/log/auth.log
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
maxretry = 6
[proftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 6
[pure-ftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = pure-ftpd
logpath = /var/log/syslog
maxretry = 6
[wuftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = wuftpd
logpath = /var/log/syslog
maxretry = 6
#
# Mail servers
#
[postfix]
enabled = true
port = smtp,ssmtp,submission
filter = postfix
logpath = /var/log/mail.log
[couriersmtp]
enabled = false
port = smtp,ssmtp,submission
filter = couriersmtp
logpath = /var/log/mail.log
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
[courierauth]
enabled = false
port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s
filter = courierlogin
logpath = /var/log/mail.log
[sasl]
enabled = true
port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s
filter = postfix-sasl
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath = /var/log/mail.log
[dovecot]
enabled = true
port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log
# To log wrong MySQL access attempts add to /etc/my.cnf:
# log-error=/var/log/mysqld.log
# log-warning = 2
[mysqld-auth]
enabled = false
filter = mysqld-auth
port = 3306
logpath = /var/log/mysqld.log
# DNS Servers
# These jails block attacks against named (bind9). By default, logging is off
# with bind9 installation. You will need something like this:
#
# logging {
# channel security_file {
# file "/var/log/named/security.log" versions 3 size 30m;
# severity dynamic;
# print-time yes;
# };
# category security {
# security_file;
# };
# };
#
# in your named.conf to provide proper logging
# !!! WARNING !!!
# Since UDP is connection-less protocol, spoofing of IP and imitation
# of illegal actions is way too simple. Thus enabling of this filter
# might provide an easy way for implementing a DoS against a chosen
# victim. See
# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
# Please DO NOT USE this jail unless you know what you are doing.
#[named-refused-udp]
#
#enabled = false
#port = domain,953
#protocol = udp
#filter = named-refused
#logpath = /var/log/named/security.log
[named-refused-tcp]
enabled = false
port = domain,953
protocol = tcp
filter = named-refused
logpath = /var/log/named/security.log
[freeswitch]
enabled = false
filter = freeswitch
logpath = /var/log/freeswitch.log
maxretry = 10
action = iptables-multiport[name=freeswitch-tcp, port="5060,5061,5080,5081", protocol=tcp]
iptables-multiport[name=freeswitch-udp, port="5060,5061,5080,5081", protocol=udp]
[ejabberd-auth]
enabled = false
filter = ejabberd-auth
port = xmpp-client
protocol = tcp
logpath = /var/log/ejabberd/ejabberd.log
# Multiple jails, 1 per protocol, are necessary ATM:
# see https://github.com/fail2ban/fail2ban/issues/37
[asterisk-tcp]
enabled = false
filter = asterisk
port = 5060,5061
protocol = tcp
logpath = /var/log/asterisk/messages
[asterisk-udp]
enabled = false
filter = asterisk
port = 5060,5061
protocol = udp
logpath = /var/log/asterisk/messages
# Jail for more extended banning of persistent abusers
# !!! WARNING !!!
# Make sure that your loglevel specified in fail2ban.conf/.local
# is not at DEBUG level -- which might then cause fail2ban to fall into
# an infinite loop constantly feeding itself with non-informative lines
[recidive]
enabled = false
filter = recidive
logpath = /var/log/fail2ban.log
action = iptables-allports[name=recidive]
sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log]
bantime = 604800 ; 1 week
findtime = 86400 ; 1 day
maxretry = 5
# See the IMPORTANT note in action.d/blocklist_de.conf for when to
# use this action
#
# Report block via blocklist.de fail2ban reporting service API
# See action.d/blocklist_de.conf for more information
[ssh-blocklist]
enabled = false
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
sendmail-whois[name=SSH, dest="%(destemail)s", sender="%(sender)s", sendername="%(sendername)s"]
blocklist_de[email="%(sender)s", apikey="xxxxxx", service="%(filter)s"]
logpath = /var/log/sshd.log
maxretry = 20
# consider low maxretry and a long bantime
# nobody except your own Nagios server should ever probe nrpe
[nagios]
enabled = false
filter = nagios
action = iptables[name=Nagios, port=5666, protocol=tcp]
sendmail-whois[name=Nagios, dest="%(destemail)s", sender="%(sender)s", sendername="%(sendername)s"]
logpath = /var/log/messages ; nrpe.cfg may define a different log_facility
maxretry = 1
[nginx]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/nginx*/*error.log
maxretry = 4
[yunohost]
enabled = true
port = http,https
protocol = tcp
filter = yunohost
logpath = /var/log/nginx/*.log

View file

@ -0,0 +1,346 @@
# Fail2Ban configuration file.
#
# This file was composed for Debian systems from the original one
# provided now under /usr/share/doc/fail2ban/examples/jail.conf
# for additional examples.
#
# To avoid merges during upgrades DO NOT MODIFY THIS FILE
# and rather provide your changes in /etc/fail2ban/jail.local
#
# Author: Yaroslav O. Halchenko <debian@onerussian.com>
#
# $Revision$
#
# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.
[DEFAULT]
# "ignoreip" can be an IP address, a CIDR mask or a DNS host
ignoreip = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
bantime = 600
maxretry = 3
# "backend" specifies the backend used to get files modification. Available
# options are "gamin", "polling" and "auto".
# yoh: For some reason Debian shipped python-gamin didn't work as expected
# This issue left ToDo, so polling is default backend for now
backend = auto
#
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = root@localhost
#
# ACTIONS
#
# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
# email action. Since 0.8.1 upstream fail2ban uses sendmail
# MTA for the mailing. Change mta configuration parameter to mail
# if you want to revert to conventional 'mail'.
mta = sendmail
# Default protocol
protocol = tcp
# Specify chain where jumps would need to be added in iptables-* actions
chain = INPUT
#
# Action shortcuts. To be used to define action parameter
# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]
# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s
#
# JAILS
#
# Next jails corresponds to the standard configuration in Fail2ban 0.6 which
# was shipped in Debian. Enable any defined here jail by including
#
# [SECTION_NAME]
# enabled = true
#
# in /etc/fail2ban/jail.local.
#
# Optionally you may override any other parameter (e.g. banaction,
# action, port, logpath, etc) in that section within jail.local
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 6
[dropbear]
enabled = false
port = ssh
filter = sshd
logpath = /var/log/dropbear
maxretry = 6
# Generic filter for pam. Has to be used with action which bans all ports
# such as iptables-allports, shorewall
[pam-generic]
enabled = false
# pam-generic filter can be customized to monitor specific subset of 'tty's
filter = pam-generic
# port actually must be irrelevant but lets leave it all for some possible uses
port = all
banaction = iptables-allports
port = anyport
logpath = /var/log/auth.log
maxretry = 6
[xinetd-fail]
enabled = false
filter = xinetd-fail
port = all
banaction = iptables-multiport-log
logpath = /var/log/daemon.log
maxretry = 2
[ssh-ddos]
enabled = false
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 6
#
# HTTP servers
#
[apache]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
# default action is now multiport, so apache-multiport jail was left
# for compatibility with previous (<0.7.6-2) releases
[apache-multiport]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/apache*/*error.log
maxretry = 6
[apache-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/apache*/*error.log
maxretry = 2
#
# FTP servers
#
[vsftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = vsftpd
logpath = /var/log/vsftpd.log
# or overwrite it in jails.local to be
# logpath = /var/log/auth.log
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
maxretry = 6
[proftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 6
[pure-ftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = pure-ftpd
logpath = /var/log/auth.log
maxretry = 6
[wuftpd]
enabled = false
port = ftp,ftp-data,ftps,ftps-data
filter = wuftpd
logpath = /var/log/auth.log
maxretry = 6
#
# Mail servers
#
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
[couriersmtp]
enabled = false
port = smtp,ssmtp
filter = couriersmtp
logpath = /var/log/mail.log
#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#
[courierauth]
enabled = false
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = courierlogin
logpath = /var/log/mail.log
[sasl]
enabled = true
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = sasl
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath = /var/log/mail.log
[dovecot]
enabled = true
port = smtp,ssmtp,imap2,imap3,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log
# DNS Servers
# These jails block attacks against named (bind9). By default, logging is off
# with bind9 installation. You will need something like this:
#
# logging {
# channel security_file {
# file "/var/log/named/security.log" versions 3 size 30m;
# severity dynamic;
# print-time yes;
# };
# category security {
# security_file;
# };
# };
#
# in your named.conf to provide proper logging
# !!! WARNING !!!
# Since UDP is connection-less protocol, spoofing of IP and imitation
# of illegal actions is way too simple. Thus enabling of this filter
# might provide an easy way for implementing a DoS against a chosen
# victim. See
# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
# Please DO NOT USE this jail unless you know what you are doing.
#[named-refused-udp]
#
#enabled = false
#port = domain,953
#protocol = udp
#filter = named-refused
#logpath = /var/log/named/security.log
[named-refused-tcp]
enabled = false
port = domain,953
protocol = tcp
filter = named-refused
logpath = /var/log/named/security.log
[nginx]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-noscript]
enabled = false
port = http,https
filter = apache-noscript
logpath = /var/log/nginx*/*error.log
maxretry = 6
[nginx-overflows]
enabled = false
port = http,https
filter = apache-overflows
logpath = /var/log/nginx*/*error.log
maxretry = 4
[yunohost]
enabled = true
port = http,https
protocol = tcp
filter = yunohost
logpath = /var/log/nginx/*.log
maxretry = 6

View file

@ -0,0 +1,24 @@
# Fail2Ban configuration file
#
# Author: Adrien Beudin
#
# $Revision: 2 $
#
[Definition]
# Option: failregex
# Notes.: regex to match the password failure messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
failregex = access.lua:[1-9]+: authenticate\(\): Connection failed for: .*, client: <HOST>
^<HOST> -.*\"POST /yunohost/api/login HTTP/1.1\" 401 22
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =

View file

@ -0,0 +1,5 @@
# Default is to launch glances with '-s' option.
DAEMON_ARGS="-s -B 127.0.0.1"
# Change to 'true' to have glances running at startup
RUN="true"

View file

@ -0,0 +1,15 @@
VirtualHost "{{ domain }}"
ssl = {
key = "/etc/yunohost/certs/{{ domain }}/key.pem";
certificate = "/etc/yunohost/certs/{{ domain }}/crt.pem";
}
authentication = "ldap2"
ldap = {
hostname = "localhost",
user = {
basedn = "ou=users,dc=yunohost,dc=org",
filter = "(&(objectClass=posixAccount)(mail=*@{{ domain }}))",
usernamefield = "mail",
namefield = "cn",
},
}

View file

@ -0,0 +1,193 @@
-- ** Metronome's config file example **
--
-- The format is exactly equal to Prosody's:
--
-- Lists are written { "like", "this", "one" }
-- Lists can also be of { 1, 2, 3 } numbers, etc.
-- Either commas, or semi-colons; may be used as seperators.
--
-- A table is a list of values, except each value has a name. An
-- example would be:
--
-- ssl = { key = "keyfile.key", certificate = "certificate.crt" }
--
-- Tip: You can check that the syntax of this file is correct when you have finished
-- by running: luac -p metronome.cfg.lua
-- If there are any errors, it will let you know what and where they are, otherwise it
-- will keep quiet.
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
-- Server PID
pidfile = "/var/run/metronome/metronome.pid"
-- HTTP server
http_ports = { 5290 }
http_interfaces = { "127.0.0.1", "::1" }
--https_ports = { 5291 }
--https_interfaces = { "127.0.0.1", "::1" }
-- Enable IPv6
use_ipv6 = true
-- This is the list of modules Metronome will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
--"discoitems"; -- Service discovery items
--"extdisco"; -- External Service Discovery
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
"privacy"; -- Support privacy lists
-- These are commented by default as they have a performance impact
--"compression"; -- Stream compression (Debian: requires lua-zlib module to work)
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"message_carbons"; -- Allow clients to keep in sync with messages send on other resources
"register"; -- Allow users to register on this server using a client and change passwords
"adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websockets"; -- Enable WebSocket clients
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
-- "bidi"; -- Bidirectional Streams for S2S connections
-- "stream_management"; -- Stream Management support
--"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
"mam"; -- Nice archive management
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
"offline"; -- Store offline messages
"c2s"; -- Handle client connections
"s2s"; -- Handle server-to-server connections
-- Debian: do not remove this module, or you lose syslog
-- support
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
};
-- Discovery items
disco_items = {
{ "muc.{{ main_domain }}" },
{ "pubsub.{{ main_domain }}" },
{ "vjud.{{ main_domain }}" }
};
-- BOSH configuration (mod_bosh)
bosh_max_inactivity = 30
consider_bosh_secure = true
cross_domain_bosh = true
-- Disable account creation by default, for security
allow_registration = false
-- SSL/TLS configuration
ssl = {
options = {
"no_sslv2",
"no_sslv3",
"no_ticket",
"no_compression",
"cipher_server_preference"
};
}
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
c2s_require_encryption = true
-- Force servers to use encrypted connections? This option will
-- prevent servers from connecting unless they are using encryption.
s2s_require_encryption = true
-- Allow servers to use an unauthenticated encryption channel
s2s_allow_encryption = true
allow_unencrypted_plain_auth = false;
s2s_secure = true
s2s_secure_auth = false
--anonymous_login = false
-- Use LDAP storage backend for all stores
storage = "ldap"
-- Logging configuration
log = {
info = "/var/log/metronome/metronome.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/metronome/metronome.err";
-- "*syslog"; -- Uncomment this for logging to syslog
-- "*console"; -- Log to the console, useful for debugging with daemonize=false
}
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
---Set up a local BOSH service
Component "localhost" "http"
modules_enabled = { "bosh" }
---Set up a MUC (multi-user chat) room server
Component "muc.{{ main_domain }}" "muc"
name = "YunoHost Chatrooms"
modules_enabled = {
"muc_limits";
"muc_log";
"muc_log_http";
}
muc_event_rate = 0.5
muc_burst_factor = 10
muc_log_http_config = {
url_base = "logs";
theme = "metronome";
}
---Set up a PubSub server
Component "pubsub.{{ main_domain }}" "pubsub"
name = "YunoHost Publish/Subscribe"
unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)
---Set up a VJUD service
Component "vjud.{{ main_domain }}" "vjud"
ud_disco_name = "Jappix User Directory"
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Metronome to serve.
-- Settings under each VirtualHost entry apply *only* to that host.
Include "conf.d/*.cfg.lua"

View file

@ -0,0 +1,119 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: metronome
# Required-Start: $network $local_fs $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Metronome XMPP Server
### END INIT INFO
set -e
# /etc/init.d/metronome: start and stop Metronome XMPP server
NAME=metronome
USER=metronome
DAEMON=/usr/bin/metronome
PIDPATH=/var/run/metronome
PIDFILE="$PIDPATH"/metronome.pid
NICE=
MAXFDS=
CPUSCHED=
IOSCHED=
test -x "$DAEMON" || exit 0
. /lib/lsb/init-functions
if [ -f /etc/default/metronome ] ; then
. /etc/default/metronome
fi
start_opts() {
test -z "$NICE" || echo -n " --nicelevel $NICE"
test -z "$CPUSCHED" || echo -n " --procsched $CPUSCHED"
test -z "$IOSCHED" || echo -n " --iosched $IOSCHED"
}
start_metronome () {
mkdir -p `dirname $PIDFILE`
chown metronome:adm `dirname $PIDFILE`
if start-stop-daemon --start --quiet --pidfile "$PIDFILE" \
--chuid "$USER" --oknodo --user "$USER" --name lua5.1 \
$(start_opts) --startas "$DAEMON";
then
return 0
else
return 1
fi
}
stop_metronome () {
if start-stop-daemon --stop --quiet --retry 30 \
--oknodo --pidfile "$PIDFILE" --user "$USER" --name lua5.1;
then
return 0
else
return 1
fi
}
signal_metronome () {
if start-stop-daemon --stop --quiet --pidfile "$PIDFILE" \
--user "$USER" --name lua5.1 --oknodo --signal $1;
then
return 0
else
return 1
fi
}
case "$1" in
start)
log_daemon_msg "Starting Metronome XMPP Server" "metronome"
if start_metronome; then
log_end_msg 0;
else
log_end_msg 1;
fi
;;
stop)
log_daemon_msg "Stopping Metronome XMPP Server" "metronome"
if stop_metronome; then
log_end_msg 0;
else
log_end_msg 1;
fi
;;
force-reload|restart)
log_daemon_msg "Restarting Metronome XMPP Server" "metronome"
stop_metronome
if start_metronome; then
log_end_msg 0;
else
log_end_msg 1;
fi
;;
reload)
log_daemon_msg "Reloading Metronome XMPP Server" "metronome"
if signal_metronome 1; then
log_end_msg 0;
else
log_end_msg 1;
fi
;;
status)
status_of_proc -p $PIDFILE $DAEMON $NAME
;;
*)
log_action_msg "Usage: /etc/init.d/metronome {start|stop|restart|reload|status}"
exit 1
esac
exit 0

View file

@ -0,0 +1,11 @@
/var/log/metronome/metronome.log /var/log/metronome/metronome.err {
daily
rotate 14
compress
create 640 metronome adm
postrotate
/etc/init.d/metronome reload > /dev/null
endscript
sharedscripts
missingok
}

View file

@ -0,0 +1,270 @@
-- vim:sts=4 sw=4
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
-- Copyright (C) 2012 Rob Hoelz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local ldap;
local connection;
local params = module:get_option("ldap");
local format = string.format;
local tconcat = table.concat;
local _M = {};
local config_params = {
hostname = 'string',
user = {
basedn = 'string',
namefield = 'string',
filter = 'string',
usernamefield = 'string',
},
groups = {
basedn = 'string',
namefield = 'string',
memberfield = 'string',
_member = {
name = 'string',
admin = 'boolean?',
},
},
admin = {
_optional = true,
basedn = 'string',
namefield = 'string',
filter = 'string',
}
}
local function run_validation(params, config, prefix)
prefix = prefix or '';
-- verify that every required member of config is present in params
for k, v in pairs(config) do
if type(k) == 'string' and k:sub(1, 1) ~= '_' then
local is_optional;
if type(v) == 'table' then
is_optional = v._optional;
else
is_optional = v:sub(-1) == '?';
end
if not is_optional and params[k] == nil then
return nil, prefix .. k .. ' is required';
end
end
end
for k, v in pairs(params) do
local expected_type = config[k];
local ok, err = true;
if type(k) == 'string' then
-- verify that this key is present in config
if k:sub(1, 1) == '_' or expected_type == nil then
return nil, 'invalid parameter ' .. prefix .. k;
end
-- type validation
if type(expected_type) == 'string' then
if expected_type:sub(-1) == '?' then
expected_type = expected_type:sub(1, -2);
end
if type(v) ~= expected_type then
return nil, 'invalid type for parameter ' .. prefix .. k;
end
else -- it's a table (or had better be)
if type(v) ~= 'table' then
return nil, 'invalid type for parameter ' .. prefix .. k;
end
-- recurse into child
ok, err = run_validation(v, expected_type, prefix .. k .. '.');
end
else -- it's an integer (or had better be)
if not config._member then
return nil, 'invalid parameter ' .. prefix .. tostring(k);
end
ok, err = run_validation(v, config._member, prefix .. tostring(k) .. '.');
end
if not ok then
return ok, err;
end
end
return true;
end
local function validate_config()
if true then
return true; -- XXX for now
end
-- this is almost too clever (I mean that in a bad
-- maintainability sort of way)
--
-- basically this allows a free pass for a key in group members
-- equal to params.groups.namefield
setmetatable(config_params.groups._member, {
__index = function(_, k)
if k == params.groups.namefield then
return 'string';
end
end
});
local ok, err = run_validation(params, config_params);
setmetatable(config_params.groups._member, nil);
if ok then
-- a little extra validation that doesn't fit into
-- my recursive checker
local group_namefield = params.groups.namefield;
for i, group in ipairs(params.groups) do
if not group[group_namefield] then
return nil, format('groups.%d.%s is required', i, group_namefield);
end
end
-- fill in params.admin if you can
if not params.admin and params.groups then
local admingroup;
for _, groupconfig in ipairs(params.groups) do
if groupconfig.admin then
admingroup = groupconfig;
break;
end
end
if admingroup then
params.admin = {
basedn = params.groups.basedn,
namefield = params.groups.memberfield,
filter = group_namefield .. '=' .. admingroup[group_namefield],
};
end
end
end
return ok, err;
end
-- what to do if connection isn't available?
local function connect()
return ldap.open_simple(params.hostname, params.bind_dn, params.bind_password, params.use_tls);
end
-- this is abstracted so we can maintain persistent connections at a later time
function _M.getconnection()
return connect();
end
function _M.getparams()
return params;
end
-- XXX consider renaming this...it doesn't bind the current connection
function _M.bind(username, password)
local conn = _M.getconnection();
local filter = format('%s=%s', params.user.usernamefield, username);
if params.user.usernamefield == 'mail' then
filter = format('mail=%s@*', username);
end
if filter then
filter = _M.filter.combine_and(filter, params.user.filter);
end
local who = _M.singlematch {
attrs = params.user.usernamefield,
base = params.user.basedn,
filter = filter,
};
if who then
who = who.dn;
module:log('debug', '_M.bind - who: %s', who);
else
module:log('debug', '_M.bind - no DN found for username = %s', username);
return nil, format('no DN found for username = %s', username);
end
local conn, err = ldap.open_simple(params.hostname, who, password, params.use_tls);
if conn then
conn:close();
return true;
end
return conn, err;
end
function _M.singlematch(query)
local ld = _M.getconnection();
query.sizelimit = 1;
query.scope = 'subtree';
for dn, attribs in ld:search(query) do
attribs.dn = dn;
return attribs;
end
end
_M.filter = {};
function _M.filter.combine_and(...)
local parts = { '(&' };
local arg = { ... };
for _, filter in ipairs(arg) do
if filter:sub(1, 1) ~= '(' and filter:sub(-1) ~= ')' then
filter = '(' .. filter .. ')'
end
parts[#parts + 1] = filter;
end
parts[#parts + 1] = ')';
return tconcat(parts, '');
end
do
local ok, err;
metronome.unlock_globals();
ok, ldap = pcall(require, 'lualdap');
metronome.lock_globals();
if not ok then
module:log("error", "Failed to load the LuaLDAP library for accessing LDAP: %s", ldap);
module:log("error", "More information on install LuaLDAP can be found at http://www.keplerproject.org/lualdap");
return;
end
if not params then
module:log("error", "LDAP configuration required to use the LDAP storage module");
return;
end
ok, err = validate_config();
if not ok then
module:log("error", "LDAP configuration is invalid: %s", tostring(err));
return;
end
end
return _M;

View file

@ -0,0 +1,81 @@
-- vim:sts=4 sw=4
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
-- Copyright (C) 2012 Rob Hoelz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
-- http://code.google.com/p/prosody-modules/source/browse/mod_auth_ldap/mod_auth_ldap.lua
-- adapted to use common LDAP store
local ldap = module:require 'ldap';
local new_sasl = require 'util.sasl'.new;
local jsplit = require 'util.jid'.split;
if not ldap then
return;
end
local provider = {}
function provider.test_password(username, password)
return ldap.bind(username, password);
end
function provider.user_exists(username)
local params = ldap.getparams()
local filter = ldap.filter.combine_and(params.user.filter, params.user.usernamefield .. '=' .. username);
if params.user.usernamefield == 'mail' then
filter = ldap.filter.combine_and(params.user.filter, 'mail=' .. username .. '@*');
end
return ldap.singlematch {
base = params.user.basedn,
filter = filter,
};
end
function provider.get_password(username)
return nil, "Passwords unavailable for LDAP.";
end
function provider.set_password(username, password)
return nil, "Passwords unavailable for LDAP.";
end
function provider.create_user(username, password)
return nil, "Account creation/modification not available with LDAP.";
end
function provider.get_sasl_handler()
local testpass_authentication_profile = {
plain_test = function(sasl, username, password, realm)
return provider.test_password(username, password), true;
end,
mechanisms = { PLAIN = true },
};
return new_sasl(module.host, testpass_authentication_profile);
end
function provider.is_admin(jid)
local admin_config = ldap.getparams().admin;
if not admin_config then
return;
end
local ld = ldap:getconnection();
local username = jsplit(jid);
local filter = ldap.filter.combine_and(admin_config.filter, admin_config.namefield .. '=' .. username);
return ldap.singlematch {
base = admin_config.basedn,
filter = filter,
};
end
module:provides("auth", provider);

View file

@ -0,0 +1,87 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local st = require "util.stanza";
local t_concat = table.concat;
local secure_auth_only = module:get_option("c2s_require_encryption")
or module:get_option("require_encryption")
or not(module:get_option("allow_unencrypted_plain_auth"));
local sessionmanager = require "core.sessionmanager";
local usermanager = require "core.usermanager";
local nodeprep = require "util.encodings".stringprep.nodeprep;
local resourceprep = require "util.encodings".stringprep.resourceprep;
module:add_feature("jabber:iq:auth");
module:hook("stream-features", function(event)
local origin, features = event.origin, event.features;
if secure_auth_only and not origin.secure then
-- Sorry, not offering to insecure streams!
return;
elseif not origin.username then
features:tag("auth", {xmlns='http://jabber.org/features/iq-auth'}):up();
end
end);
module:hook("stanza/iq/jabber:iq:auth:query", function(event)
local session, stanza = event.origin, event.stanza;
if session.type ~= "c2s_unauthed" then
(session.sends2s or session.send)(st.error_reply(stanza, "cancel", "service-unavailable", "Legacy authentication is only allowed for unauthenticated client connections."));
return true;
end
if secure_auth_only and not session.secure then
session.send(st.error_reply(stanza, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
return true;
end
local username = stanza.tags[1]:child_with_name("username");
local password = stanza.tags[1]:child_with_name("password");
local resource = stanza.tags[1]:child_with_name("resource");
if not (username and password and resource) then
local reply = st.reply(stanza);
session.send(reply:query("jabber:iq:auth")
:tag("username"):up()
:tag("password"):up()
:tag("resource"):up());
else
username, password, resource = t_concat(username), t_concat(password), t_concat(resource);
username = nodeprep(username);
resource = resourceprep(resource)
if not (username and resource) then
session.send(st.error_reply(stanza, "modify", "bad-request"));
return true;
end
if usermanager.test_password(username, session.host, password) then
-- Authentication successful!
local success, err = sessionmanager.make_authenticated(session, username);
if success then
local err_type, err_msg;
success, err_type, err, err_msg = sessionmanager.bind_resource(session, resource);
if not success then
session.send(st.error_reply(stanza, err_type, err, err_msg));
session.username, session.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
return true;
elseif resource ~= session.resource then -- server changed resource, not supported by legacy auth
session.send(st.error_reply(stanza, "cancel", "conflict", "The requested resource could not be assigned to this session."));
session:close(); -- FIXME undo resource bind and auth instead of closing the session?
return true;
end
end
session.send(st.reply(stanza));
else
session.send(st.error_reply(stanza, "auth", "not-authorized"));
end
end
return true;
end);

View file

@ -0,0 +1,180 @@
-- vim:sts=4 sw=4
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
-- Copyright (C) 2012 Rob Hoelz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
----------------------------------------
-- Constants and such --
----------------------------------------
local setmetatable = setmetatable;
local ldap = module:require 'ldap';
local vcardlib = module:require 'vcard';
local st = require 'util.stanza';
local gettime = require 'socket'.gettime;
if not ldap then
return;
end
local CACHE_EXPIRY = 300;
local params = module:get_option('ldap');
----------------------------------------
-- Utility Functions --
----------------------------------------
local function ldap_record_to_vcard(record)
return vcardlib.create {
record = record,
format = params.vcard_format,
}
end
local get_alias_for_user;
do
local user_cache;
local last_fetch_time;
local function populate_user_cache()
local ld = ldap.getconnection();
local usernamefield = params.user.usernamefield;
local namefield = params.user.namefield;
user_cache = {};
for _, attrs in ld:search { base = params.user.basedn, scope = 'onelevel', filter = params.user.filter } do
user_cache[attrs[usernamefield]] = attrs[namefield];
end
last_fetch_time = gettime();
end
function get_alias_for_user(user)
if last_fetch_time and last_fetch_time + CACHE_EXPIRY < gettime() then
user_cache = nil;
end
if not user_cache then
populate_user_cache();
end
return user_cache[user];
end
end
----------------------------------------
-- General Setup --
----------------------------------------
local ldap_store = {};
ldap_store.__index = ldap_store;
local adapters = {
roster = {},
vcard = {},
}
for k, v in pairs(adapters) do
setmetatable(v, ldap_store);
v.__index = v;
v.name = k;
end
function ldap_store:get(username)
return nil, "get method unimplemented on store '" .. tostring(self.name) .. "'"
end
function ldap_store:set(username, data)
return nil, "LDAP storage is currently read-only";
end
----------------------------------------
-- Roster Storage Implementation --
----------------------------------------
function adapters.roster:get(username)
local ld = ldap.getconnection();
local contacts = {};
local memberfield = params.groups.memberfield;
local namefield = params.groups.namefield;
local filter = memberfield .. '=' .. tostring(username);
local groups = {};
for _, config in ipairs(params.groups) do
groups[ config[namefield] ] = config.name;
end
-- XXX this kind of relies on the way we do groups at INOC
for _, attrs in ld:search { base = params.groups.basedn, scope = 'onelevel', filter = filter } do
if groups[ attrs[namefield] ] then
local members = attrs[memberfield];
for _, user in ipairs(members) do
if user ~= username then
local jid = user .. '@' .. module.host;
local record = contacts[jid];
if not record then
record = {
subscription = 'both',
groups = {},
name = get_alias_for_user(user),
};
contacts[jid] = record;
end
record.groups[ groups[ attrs[namefield] ] ] = true;
end
end
end
end
return contacts;
end
----------------------------------------
-- vCard Storage Implementation --
----------------------------------------
function adapters.vcard:get(username)
if not params.vcard_format then
return nil, '';
end
local ld = ldap.getconnection();
local filter = params.user.usernamefield .. '=' .. tostring(username);
local match = ldap.singlematch {
base = params.user.basedn,
filter = filter,
};
if match then
match.jid = username .. '@' .. module.host
return st.preserialize(ldap_record_to_vcard(match));
else
return nil, 'not found';
end
end
----------------------------------------
-- Driver Definition --
----------------------------------------
local driver = {};
function driver:open(store, typ)
local adapter = adapters[store];
if adapter and not typ then
return adapter;
end
return nil, "unsupported-store";
end
module:provides("storage", driver);

View file

@ -0,0 +1,162 @@
-- vim:sts=4 sw=4
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
-- Copyright (C) 2012 Rob Hoelz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local st = require 'util.stanza';
local VCARD_NS = 'vcard-temp';
local builder_methods = {};
local base64_encode = require('util.encodings').base64.encode;
function builder_methods:addvalue(key, value)
self.vcard:tag(key):text(value):up();
end
function builder_methods:addphotofield(tagname, format_section)
local record = self.record;
local format = self.format;
local vcard = self.vcard;
local config = format[format_section];
if not config then
return;
end
if config.extval then
if record[config.extval] then
local tag = vcard:tag(tagname);
tag:tag('EXTVAL'):text(record[config.extval]):up();
end
elseif config.type and config.binval then
if record[config.binval] then
local tag = vcard:tag(tagname);
tag:tag('TYPE'):text(config.type):up();
tag:tag('BINVAL'):text(base64_encode(record[config.binval])):up();
end
else
module:log('error', 'You have an invalid %s config section', tagname);
return;
end
vcard:up();
end
function builder_methods:addregularfield(tagname, format_section)
local record = self.record;
local format = self.format;
local vcard = self.vcard;
if not format[format_section] then
return;
end
local tag = vcard:tag(tagname);
for k, v in pairs(format[format_section]) do
tag:tag(string.upper(k)):text(record[v]):up();
end
vcard:up();
end
function builder_methods:addmultisectionedfield(tagname, format_section)
local record = self.record;
local format = self.format;
local vcard = self.vcard;
if not format[format_section] then
return;
end
for k, v in pairs(format[format_section]) do
local tag = vcard:tag(tagname);
if type(k) == 'string' then
tag:tag(string.upper(k)):up();
end
for k2, v2 in pairs(v) do
if type(v2) == 'boolean' then
tag:tag(string.upper(k2)):up();
else
tag:tag(string.upper(k2)):text(record[v2]):up();
end
end
vcard:up();
end
end
function builder_methods:build()
local record = self.record;
local format = self.format;
self:addvalue( 'VERSION', '2.0');
self:addvalue( 'FN', record[format.displayname]);
self:addregularfield( 'N', 'name');
self:addvalue( 'NICKNAME', record[format.nickname]);
self:addphotofield( 'PHOTO', 'photo');
self:addvalue( 'BDAY', record[format.birthday]);
self:addmultisectionedfield('ADR', 'address');
self:addvalue( 'LABEL', nil); -- we don't support LABEL...yet.
self:addmultisectionedfield('TEL', 'telephone');
self:addmultisectionedfield('EMAIL', 'email');
self:addvalue( 'JABBERID', record.jid);
self:addvalue( 'MAILER', record[format.mailer]);
self:addvalue( 'TZ', record[format.timezone]);
self:addregularfield( 'GEO', 'geo');
self:addvalue( 'TITLE', record[format.title]);
self:addvalue( 'ROLE', record[format.role]);
self:addphotofield( 'LOGO', 'logo');
self:addvalue( 'AGENT', nil); -- we don't support AGENT...yet.
self:addregularfield( 'ORG', 'org');
self:addvalue( 'CATEGORIES', nil); -- we don't support CATEGORIES...yet.
self:addvalue( 'NOTE', record[format.note]);
self:addvalue( 'PRODID', nil); -- we don't support PRODID...yet.
self:addvalue( 'REV', record[format.rev]);
self:addvalue( 'SORT-STRING', record[format.sortstring]);
self:addregularfield( 'SOUND', 'sound');
self:addvalue( 'UID', record[format.uid]);
self:addvalue( 'URL', record[format.url]);
self:addvalue( 'CLASS', nil); -- we don't support CLASS...yet.
self:addregularfield( 'KEY', 'key');
self:addvalue( 'DESC', record[format.description]);
return self.vcard;
end
local function new_builder(params)
local vcard_tag = st.stanza('vCard', { xmlns = VCARD_NS });
local object = {
vcard = vcard_tag,
__index = builder_methods,
};
for k, v in pairs(params) do
object[k] = v;
end
setmetatable(object, object);
return object;
end
local _M = {};
function _M.create(params)
local builder = new_builder(params);
return builder:build();
end
return _M;

View file

@ -0,0 +1,89 @@
# Example MySQL config file for small systems.
#
# This is for a system with little memory (<= 64M) where MySQL is only used
# from time to time and it's important that the mysqld daemon
# doesn't use much resources.
#
# MySQL programs look for option files in a set of
# locations which depend on the deployment platform.
# You can copy this option file to one of those
# locations. For information about these locations, see:
# http://dev.mysql.com/doc/mysql/en/option-files.html
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.
# The following options will be passed to all MySQL clients
[client]
#password = your_password
port = 3306
socket = /var/run/mysqld/mysqld.sock
# Here follows entries for some specific programs
# The MySQL server
[mysqld]
port = 3306
socket = /var/run/mysqld/mysqld.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 128K
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (using the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
server-id = 1
# Uncomment the following if you want to log updates
#log-bin=mysql-bin
# binary logging format - mixed recommended
#binlog_format=mixed
# Causes updates to non-transactional engines using statement format to be
# written directly to binary log. Before using this option make sure that
# there are no dependencies between transactional and non-transactional
# tables such as in the statement INSERT INTO t_myisam SELECT * FROM
# t_innodb; otherwise, slaves may diverge from the master.
#binlog_direct_non_transactional_updates=TRUE
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = /var/lib/mysql
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = /var/lib/mysql
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
[mysqlhotcopy]
interactive-timeout

View file

@ -0,0 +1,46 @@
server {
listen 80;
listen [::]:80;
server_name {{ domain }};
access_by_lua_file /usr/share/ssowat/access.lua;
include conf.d/{{ domain }}.d/*.conf;
location /yunohost/admin {
rewrite ^ https://$http_host$request_uri? permanent;
}
access_log /var/log/nginx/{{ domain }}-access.log;
error_log /var/log/nginx/{{ domain }}-error.log;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {{ domain }};
ssl_certificate /etc/yunohost/certs/{{ domain }}/crt.pem;
ssl_certificate_key /etc/yunohost/certs/{{ domain }}/key.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM;
add_header Strict-Transport-Security "max-age=31536000;";
# Uncomment the following directive after DH generation
# > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
#ssl_dhparam /etc/ssl/private/dh2048.pem;
access_by_lua_file /usr/share/ssowat/access.lua;
include conf.d/{{ domain }}.d/*.conf;
include conf.d/yunohost_admin.conf.inc;
include conf.d/yunohost_api.conf.inc;
access_log /var/log/nginx/{{ domain }}-access.log;
error_log /var/log/nginx/{{ domain }}-error.log;
}

View file

@ -0,0 +1,3 @@
lua_shared_dict cache 10m;
init_by_lua_file /usr/share/ssowat/init.lua;
server_names_hash_bucket_size 64;

View file

@ -0,0 +1,35 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
rewrite ^ https://$http_host/yunohost/admin permanent;
}
location /yunohost/admin {
rewrite ^ https://$http_host$request_uri? permanent;
}
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/yunohost/certs/yunohost.org/crt.pem;
ssl_certificate_key /etc/yunohost/certs/yunohost.org/key.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM;
add_header Strict-Transport-Security "max-age=31536000;";
location / {
rewrite ^ https://$http_host/yunohost/admin permanent;
}
# Block crawlers bot
location /yunohost {
if ($http_user_agent ~ (crawl|Googlebot|Slurp|spider|bingbot|tracker|click|parser|spider|facebookexternalhit) ) {
return 403;
}
}
include conf.d/yunohost_admin.conf.inc;
include conf.d/yunohost_api.conf.inc;
}

View file

@ -0,0 +1,5 @@
location /yunohost/admin {
alias /usr/share/yunohost/admin/;
default_type text/html;
index index.html;
}

View file

@ -0,0 +1,7 @@
location /yunohost/api/ {
proxy_read_timeout 3600s;
proxy_pass http://127.0.0.1:6787/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

View file

@ -0,0 +1 @@
server_name $server_name yunohost.local;

View file

@ -0,0 +1,2 @@
sub_filter <head> '<head><script type="text/javascript" src="/ynhpanel.js"></script>';
sub_filter_once on;

View file

@ -0,0 +1,38 @@
# /etc/nslcd.conf
# nslcd configuration file. See nslcd.conf(5)
# for details.
# The user and group nslcd should run as.
uid nslcd
gid nslcd
# The location at which the LDAP server(s) should be reachable.
uri ldap://localhost/
# The search base that will be used for all queries.
base dc=yunohost,dc=org
# The LDAP protocol version to use.
#ldap_version 3
# The DN to bind with for normal lookups.
#binddn cn=annonymous,dc=example,dc=net
#bindpw secret
# The DN used for password modifications by root.
#rootpwmoddn cn=admin,dc=example,dc=com
# SSL options
#ssl off
#tls_reqcert never
tls_cacertfile /etc/ssl/certs/ca-certificates.crt
# The search scope.
#scope sub

View file

@ -0,0 +1,21 @@
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: compat ldap
group: compat ldap
shadow: compat ldap
gshadow: files
hosts: files mdns4_minimal [NOTFOUND=return] dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
sudoers: files ldap

View file

@ -0,0 +1,4 @@
/^X-Originating-IP:/ IGNORE
/^Received:/ IGNORE
/^User-Agent:/ IGNORE
/^X-Mailer:/ IGNORE

View file

@ -0,0 +1,5 @@
server_host = localhost
server_port = 389
search_base = dc=yunohost,dc=org
query_filter = (&(objectClass=mailAccount)(mail=%s))
result_attribute = uid

View file

@ -0,0 +1,5 @@
server_host = localhost
server_port = 389
search_base = dc=yunohost,dc=org
query_filter = (&(objectClass=mailAccount)(mail=%s))
result_attribute = maildrop

View file

@ -0,0 +1,5 @@
server_host = localhost
server_port = 389
search_base = ou=domains,dc=yunohost,dc=org
query_filter = (&(objectClass=mailDomain)(virtualdomain=%s))
result_attribute = virtualdomain

View file

@ -0,0 +1,145 @@
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
smtpd_banner = $myhostname Service ready
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# -- TLS for incoming connections
# By default, TLS is disabled in the Postfix SMTP server, so no difference to
# plain Postfix is visible. Explicitly switch it on with "smtpd_tls_security_level = may".
smtpd_tls_security_level=may
# Sending AUTH data over an unencrypted channel poses a security risk.
# When TLS layer encryption is optional ("smtpd_tls_security_level = may"), it
# may however still be useful to only offer AUTH when TLS is active. To maintain
# compatibility with non-TLS clients, the default is to accept AUTH without
# encryption. In order to change this behavior, we set "smtpd_tls_auth_only = yes".
smtpd_tls_auth_only=yes
smtpd_tls_cert_file=/etc/ssl/certs/yunohost_crt.pem
smtpd_tls_key_file=/etc/ssl/private/yunohost_key.pem
smtpd_tls_CAfile = /etc/ssl/certs/ca-yunohost_crt.pem
smtpd_tls_exclude_ciphers = aNULL, MD5, DES, ADH, RC4
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_loglevel=1
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
smtpd_tls_mandatory_ciphers=high
# -- TLS for outgoing connections
# Use TLS if this is supported by the remote SMTP server, otherwise use plaintext.
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_loglevel=1
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
myhostname = {{ main_domain }}
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydomain = {{ main_domain }}
mydestination = localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
#### Fit to the maximum message size allowed by GMail or Yahoo ####
message_size_limit = 26214400
# Virtual Domains Control
virtual_mailbox_domains = ldap:/etc/postfix/ldap-domains.cf
virtual_mailbox_maps = ldap:/etc/postfix/ldap-accounts.cf
virtual_mailbox_base =
virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf
virtual_alias_domains =
virtual_minimum_uid = 100
virtual_uid_maps = static:vmail
virtual_gid_maps = static:mail
# Dovecot LDA
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
# Enable SASL authentication for the smtpd daemon
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
# Fix some outlook's bugs
broken_sasl_auth_clients = yes
# Reject anonymous connections
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain =
# Use AMaVis
content_filter = amavis:[127.0.0.1]:10024
# Wait until the RCPT TO command before evaluating restrictions
smtpd_delay_reject = yes
# Basics Restrictions
smtpd_helo_required = yes
strict_rfc821_envelopes = yes
# Requirements for the connecting server
smtpd_client_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_rbl_client bl.spamcop.net,
reject_rbl_client cbl.abuseat.org,
reject_rbl_client zen.spamhaus.org,
permit
# Requirements for the HELO statement
smtpd_helo_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_non_fqdn_hostname,
reject_invalid_hostname,
permit
# Requirements for the sender address
smtpd_sender_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
permit
# Requirement for the recipient address
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
reject_unauth_destination,
check_policy_service unix:private/policy-spf
check_policy_service inet:127.0.0.1:10023
permit
# Use SPF
policy-spf_time_limit = 3600s
# SRS
sender_canonical_maps = regexp:/etc/postfix/sender_canonical
sender_canonical_classes = envelope_sender
# Ignore some headers
smtp_header_checks = regexp:/etc/postfix/header_checks
smtp_reply_filter = pcre:/etc/postfix/smtp_reply_filter

View file

@ -0,0 +1,147 @@
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - - - - smtpd
submission inet n - - - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
smtps inet n - - - - smtpd
-o header_checks=pcre:/etc/postfix/header_checks
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#628 inet n - - - - qmqpd
pickup fifo n - - 60 1 pickup
cleanup unix n - - - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - - 300 1 oqmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay unix - - - - - smtp
-o smtp_fallback_relay=
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
# Dovecot LDA
dovecot unix - n n - - pipe
flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -m ${extension}
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
# Added using postfix-add-filter script:
amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o smtp_tls_note_starttls_offer=no
policy-spf unix - n n - - spawn
user=nobody argv=/usr/bin/perl /usr/sbin/postfix-policyd-spf-perl
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o smtpd_restriction_classes=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
-o local_header_rewrite_clients=
-o smtpd_milters=
-o local_recipient_maps=
-o relay_recipient_maps=

View file

@ -0,0 +1 @@
/^(.*)@(.*)$/ ${1}

View file

@ -0,0 +1,8 @@
# Google Mail bounces email sent via IPv6, while this works ok with IPv4.
#
# Convert Google Mail IPv6 complaint permanent error into a temporary error.
# Turn 550 error containing gsmtp in the message into 450 error.
# This way Postfix will attempt to deliver this e-mail using another MX
# (via IPv4).
#
/^5(\d\d )5(.*information. \S+ - gsmtp.*)/ 4${1}4$2

View file

@ -0,0 +1,12 @@
# postgrey startup options, created for Debian
# you may want to set
# --delay=N how long to greylist, seconds (default: 300)
# --max-age=N delete old entries after N days (default: 35)
# see also the postgrey(8) manpage
POSTGREY_OPTS="--inet=10023 --delay=30"
# the --greylist-text commandline argument can not be easily passed through
# POSTGREY_OPTS when it contains spaces. So, insert your text here:
#POSTGREY_TEXT="Your customized rejection message here"

View file

@ -0,0 +1,18 @@
#
# LDAP Defaults
#
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
#BASE dc=example,dc=com
#URI ldap://ldap.example.com ldap://ldap-master.example.com:666
#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never
# TLS certificates (needed for GnuTLS)
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
sudoers_base ou=sudo,dc=yunohost,dc=org

View file

@ -0,0 +1,88 @@
## LDAP Schema Yunohost EMAIL
## Version 0.1
## Adrien Beudin
# Attributes
attributetype ( 1.3.6.1.4.1.40328.1.20.2.1
NAME 'maildrop'
DESC 'Mail addresses where mails are forwarded -- ie forwards'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.2
NAME 'mailalias'
DESC 'Mail addresses accepted by this account -- ie aliases'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.3
NAME 'mailenable'
DESC 'Mail Account validity'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{8})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.4
NAME 'mailbox'
DESC 'Mailbox path where mails are delivered'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.5
NAME 'virtualdomain'
DESC 'A mail domain name'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.6
NAME 'virtualdomaindescription'
DESC 'Virtual domain description'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512})
attributetype ( 1.3.6.1.4.1.40328.1.20.2.7
NAME 'mailuserquota'
DESC 'Mailbox quota for a user'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} SINGLE-VALUE )
# Mail Account Objectclass
objectclass ( 1.3.6.1.4.1.40328.1.1.2.1
NAME 'mailAccount'
DESC 'Mail Account'
SUP top
AUXILIARY
MUST (
mail
)
MAY (
mailalias $ maildrop $ mailenable $ mailbox $ mailuserquota
)
)
# Mail Domain Objectclass
objectclass ( 1.3.6.1.4.1.40328.1.1.2.2
NAME 'mailDomain'
DESC 'Domain mail entry'
SUP top
STRUCTURAL
MUST (
virtualdomain
)
MAY (
virtualdomaindescription $ mailuserquota
)
)
# Mail Group Objectclass
objectclass ( 1.3.6.1.4.1.40328.1.1.2.3
NAME 'mailGroup' SUP top AUXILIARY
DESC 'Mail Group'
MUST ( mail )
)

View file

@ -0,0 +1,142 @@
# This is the main slapd configuration file. See slapd.conf(5) for more
# info on the configuration options.
#######################################################################
# Global Directives:
# Features to permit
#allow bind_v2
# Schema and objectClass definitions
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/mailserver.schema
include /etc/ldap/schema/sudo.schema
# Where the pid file is put. The init.d script
# will not stop the server if you change this.
pidfile /var/run/slapd/slapd.pid
# List of arguments that were passed to the server
argsfile /var/run/slapd/slapd.args
password-hash {SSHA}
# Read slapd.conf(5) for possible values
loglevel 256
# Where the dynamically loaded modules are stored
modulepath /usr/lib/ldap
moduleload back_hdb
moduleload memberof
# The maximum number of entries that is returned for a search operation
sizelimit 500
# The tool-threads parameter sets the actual amount of cpu's that is used
# for indexing.
tool-threads 1
#######################################################################
# Specific Backend Directives for hdb:
# Backend specific directives apply to this backend until another
# 'backend' directive occurs
backend hdb
#######################################################################
# Specific Backend Directives for 'other':
# Backend specific directives apply to this backend until another
# 'backend' directive occurs
#backend <other>
#######################################################################
# Specific Directives for database #1, of type hdb:
# Database specific directives apply to this databasse until another
# 'database' directive occurs
database hdb
# The base of your directory in database #1
suffix "dc=yunohost,dc=org"
directory "/var/lib/ldap"
# The dbconfig settings are used to generate a DB_CONFIG file the first
# time slapd starts. They do NOT override existing an existing DB_CONFIG
# file. You should therefore change these settings in DB_CONFIG directly
# or remove DB_CONFIG and restart slapd for changes to take effect.
# For the Debian package we use 2MB as default but be sure to update this
# value if you have plenty of RAM
dbconfig set_cachesize 0 2097152 0
# Sven Hartge reported that he had to set this value incredibly high
# to get slapd running at all. See http://bugs.debian.org/303057 for more
# information.
# Number of objects that can be locked at the same time.
dbconfig set_lk_max_objects 1500
# Number of locks (both requested and granted)
dbconfig set_lk_max_locks 1500
# Number of lockers
dbconfig set_lk_max_lockers 1500
# Indexing options for database #1
index objectClass eq
index uid eq,sub
index entryCSN,entryUUID eq
# Save the time that the entry gets modified, for database #1
lastmod on
# Checkpoint the BerkeleyDB database periodically in case of system
# failure and to speed slapd shutdown.
checkpoint 512 30
# Where to store the replica logs for database #1
# replogfile /var/lib/ldap/replog
# The userPassword by default can be changed
# by the entry owning it if they are authenticated.
# Others should not be able to see it, except the
# admin entry below
# These access lines apply to database #1 only
access to attrs=userPassword
by dn="cn=admin,dc=yunohost,dc=org" write
by anonymous auth
by self write
by * none
access to attrs=cn,gecos,givenName,mail,maildrop,displayName,sn
by dn="cn=admin,dc=yunohost,dc=org" write
by self write
by * read
# Ensure read access to the base for things like
# supportedSASLMechanisms. Without this you may
# have problems with SASL not knowing what
# mechanisms are available and the like.
# Note that this is covered by the 'access to *'
# ACL below too but if you change that as people
# are wont to do you'll still need this if you
# want SASL (and possible other things) to work
# happily.
access to dn.base="" by * read
# The admin dn has full write access, everyone else
# can read everything.
access to *
by dn="cn=admin,dc=yunohost,dc=org" write
by group/groupOfNames/Member="cn=admin,ou=groups,dc=yunohost,dc=org" write
by * read
#######################################################################
# Specific Directives for database #2, of type 'other' (can be hdb too):
# Database specific directives apply to this databasse until another
# 'database' directive occurs
#database <other>
# The base of your directory for database #2
#suffix "dc=debian,dc=org"

View file

@ -0,0 +1,45 @@
# Default location of the slapd.conf file or slapd.d cn=config directory. If
# empty, use the compiled-in default (/etc/ldap/slapd.d with a fallback to
# /etc/ldap/slapd.conf).
SLAPD_CONF=
# System account to run the slapd server under. If empty the server
# will run as root.
SLAPD_USER="openldap"
# System group to run the slapd server under. If empty the server will
# run in the primary group of its user.
SLAPD_GROUP="openldap"
# Path to the pid file of the slapd server. If not set the init.d script
# will try to figure it out from $SLAPD_CONF (/etc/ldap/slapd.conf by
# default)
SLAPD_PIDFILE=
# slapd normally serves ldap only on all TCP-ports 389. slapd can also
# service requests on TCP-port 636 (ldaps) and requests via unix
# sockets.
# Example usage:
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
SLAPD_SERVICES="ldap:/// ldapi:///"
# If SLAPD_NO_START is set, the init script will not start or restart
# slapd (but stop will still work). Uncomment this if you are
# starting slapd via some other means or if you don't want slapd normally
# started at boot.
#SLAPD_NO_START=1
# If SLAPD_SENTINEL_FILE is set to path to a file and that file exists,
# the init script will not start or restart slapd (but stop will still
# work). Use this for temporarily disabling startup of slapd (when doing
# maintenance, for example, or through a configuration management system)
# when you don't want to edit a configuration file.
SLAPD_SENTINEL_FILE=/etc/ldap/noslapd
# For Kerberos authentication (via SASL), slapd by default uses the system
# keytab file (/etc/krb5.keytab). To use a different keytab file,
# uncomment this line and change the path.
#export KRB5_KTNAME=/etc/krb5.keytab
# Additional options to pass to slapd
SLAPD_OPTIONS=""

View file

@ -0,0 +1,76 @@
#
# OpenLDAP schema file for Sudo
# Save as /etc/openldap/schema/sudo.schema
#
attributetype ( 1.3.6.1.4.1.15953.9.1.1
NAME 'sudoUser'
DESC 'User(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.2
NAME 'sudoHost'
DESC 'Host(s) who may run sudo'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.3
NAME 'sudoCommand'
DESC 'Command(s) to be executed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.4
NAME 'sudoRunAs'
DESC 'User(s) impersonated by sudo (deprecated)'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.5
NAME 'sudoOption'
DESC 'Options(s) followed by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.6
NAME 'sudoRunAsUser'
DESC 'User(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.7
NAME 'sudoRunAsGroup'
DESC 'Group(s) impersonated by sudo'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.15953.9.1.8
NAME 'sudoNotBefore'
DESC 'Start of time interval for which the entry is valid'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributetype ( 1.3.6.1.4.1.15953.9.1.9
NAME 'sudoNotAfter'
DESC 'End of time interval for which the entry is valid'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributeTypes ( 1.3.6.1.4.1.15953.9.1.10
NAME 'sudoOrder'
DESC 'an integer to order the sudoRole entries'
EQUALITY integerMatch
ORDERING integerOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
DESC 'Sudoer Entries'
MUST ( cn )
MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $
description )
)

View file

@ -0,0 +1,94 @@
# This is the right place to customize your installation of SpamAssassin.
report_safe 0
lock_method flock
# Bayes-related operations
use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1
bayes_auto_expire 1
bayes_path /var/lib/amavis/.spamassassin/bayes
bayes_file_mode 0777
# External network tests
dns_available yes
skip_rbl_checks 0
use_razor2 1
use_pyzor 1
# Use URIBL (http://www.uribl.com/about.shtml)
urirhssub URIBL_BLACK multi.uribl.com. A 2
body URIBL_BLACK eval:check_uridnsbl('URIBL_BLACK')
describe URIBL_BLACK Contains an URL listed in the URIBL blacklist
tflags URIBL_BLACK net
score URIBL_BLACK 3.0
urirhssub URIBL_GREY multi.uribl.com. A 4
body URIBL_GREY eval:check_uridnsbl('URIBL_GREY')
describe URIBL_GREY Contains an URL listed in the URIBL greylist
tflags URIBL_GREY net
score URIBL_GREY 0.25
# Use SURBL (http://www.surbl.org/)
urirhssub URIBL_JP_SURBL multi.surbl.org. A 64
body URIBL_JP_SURBL eval:check_uridnsbl('URIBL_JP_SURBL')
describe URIBL_JP_SURBL Has URI in JP at http://www.surbl.org/lists.html
tflags URIBL_JP_SURBL net
score URIBL_JP_SURBL 3.0
score SPF_FAIL 10.000
score SPF_HELO_FAIL 10.000
score RAZOR2_CHECK 2.500
score RAZOR2_CF_RANGE_51_100 3.500
#
# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be
# tweaked.
#
# Only a small subset of options are listed below
#
###########################################################################
# Add *****SPAM***** to the Subject header of spam e-mails
#
# rewrite_header Subject *****SPAM*****
# Save spam messages as a message/rfc822 MIME attachment instead of
# modifying the original message (0: off, 2: use text/plain instead)
#
# report_safe 1
# Set which networks or hosts are considered 'trusted' by your mail
# server (i.e. not spammers)
#
# trusted_networks 212.17.35.
# Set file-locking method (flock is not safe over NFS, but is faster)
#
# lock_method flock
# Set the threshold at which a message is considered spam (default: 5.0)
#
# required_score 5.0
# Use Bayesian classifier (default: 1)
#
# use_bayes 1
# Bayesian classifier auto-learning (default: 1)
#
# bayes_auto_learn 1
# Set headers which may provide inappropriate cues to the Bayesian
# classifier
#
# bayes_ignore_header X-Bogosity
# bayes_ignore_header X-Spam-Flag
# bayes_ignore_header X-Spam-Status

View file

@ -0,0 +1,31 @@
# /etc/default/spamassassin
# Duncan Findlay
# WARNING: please read README.spamd before using.
# There may be security risks.
# Change to one to enable spamd
ENABLED=0
# Options
# See man spamd for possible options. The -d option is automatically added.
# SpamAssassin uses a preforking model, so be careful! You need to
# make sure --max-children is not set to anything higher than 5,
# unless you know what you're doing.
OPTIONS="--create-prefs --max-children 5 --helper-home-dir"
# Pid file
# Where should spamd write its PID to file? If you use the -u or
# --username option above, this needs to be writable by that user.
# Otherwise, the init script will not be able to shut spamd down.
PIDFILE="/var/run/spamd.pid"
# Set nice level of spamd
#NICE="--nicelevel 15"
# Cronjob
# Set to anything but 0 to enable the cron job to automatically update
# spamassassin's rules on a nightly basis
CRON=1

View file

@ -0,0 +1,93 @@
# Package generated configuration file
# See the sshd_config(5) manpage for details
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
ListenAddress ::
ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes
# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 768
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes
# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Change to no to disable tunnelled clear text passwords
#PasswordAuthentication yes
# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no
#MaxStartups 10:30:60
Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
Subsystem sftp internal-sftp
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
Match User sftpusers
ForceCommand internal-sftp
ChrootDirectory /home/%u
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no

View file

@ -0,0 +1,293 @@
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = /usr/share/yunohost/yunohost-config/ssl
RANDFILE = $ENV::HOME/.rnd
# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca' and 'req'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
####################################################################
[ ca ]
default_ca = Yunohost # The default ca section
####################################################################
[ Yunohost ]
dir = /usr/share/yunohost/yunohost-config/ssl/yunoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/ca/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
#crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/ca/cakey.pem # The private key
RANDFILE = $dir/ca/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 3650 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha256 # which md to use.
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString.
# utf8only: only UTF8Strings.
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
# so use this option with caution!
string_mask = nombstr
req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = yunohost.org
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName=DNS:yunohost.org,DNS:www.yunohost.org,DNS:ns.yunohost.org
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true
# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

View file

@ -0,0 +1,9 @@
filter disks {
optical = false
partition_table = false
usage = filesystem
}
match disks {
automount=true
automount_options= { sync, noatime, "dmask=0", "fmask=0" }
}

View file

@ -0,0 +1,6 @@
02periodic 50unattended-upgrades
root@65ba01d0c078:/usr/share/yunohost/yunohost-config/unattended# cat 02periodic
APT::Periodic::Enable "1";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Verbose "1";

View file

@ -0,0 +1,36 @@
// Automatically upgrade packages from these (origin, archive) pairs
Unattended-Upgrade::Allowed-Origins {
"${distro_id} stable";
"${distro_id} testing";
"Depot-Debian testing";
"${distro_id} ${distro_codename}-security";
"${distro_id} ${distro_codename}-updates";
// "${distro_id} ${distro_codename}-proposed-updates";
};
// List of packages to not update
Unattended-Upgrade::Package-Blacklist {
// "vim";
// "libc6";
// "libc6-dev";
// "libc6-i686";
};
// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. The package 'mailx'
// must be installed or anything that provides /usr/bin/mail.
//Unattended-Upgrade::Mail "root@localhost";
// Do automatic removal of new unused dependencies after the upgrade
// (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";
// Automatically reboot *WITHOUT CONFIRMATION* if a
// the file /var/run/reboot-required is found after the upgrade
Unattended-Upgrade::Automatic-Reboot "false";
// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";

View file

@ -39,3 +39,13 @@ postgrey:
amavis:
status: service
log: /var/log/mail.log
nslcd:
status: service
log: /var/log/syslog
nsswitch:
status: service
spamassassin:
status: service
log: /var/log/mail.log
udisks-glue:
status: service

36
debian/control vendored
View file

@ -1,14 +1,15 @@
Source: moulinette-yunohost
Section: net
Source: yunohost
Section: utils
Priority: extra
Maintainer: Jérôme Lebleu <jerome.lebleu@mailoo.org>
Build-Depends: debhelper (>=8.0.0)
Standards-Version: 3.9.4
Maintainer: YunoHost Contributors <contrib@yunohost.org>
Build-Depends: debhelper (>=9), dh-systemd
Standards-Version: 3.9.6
Homepage: https://yunohost.org/
Package: moulinette-yunohost
Package: yunohost
Architecture: all
Depends: moulinette (>= 2.2.1),
Depends: ${misc:Depends}, ${shlibs:Depends},
moulinette (>= 2.2.1),
python-psutil,
python-requests,
glances,
@ -25,6 +26,23 @@ Depends: moulinette (>= 2.2.1),
git-core,
curl,
mariadb-server | mysql-server, php5-mysql | php5-mysqlnd
slapd, ldap-utils, sudo-ldap, libnss-ldapd,
postfix-ldap, postfix-policyd-spf-perl, postfix-pcre, postgrey,
dovecot-ldap, dovecot-lmtpd, dovecot-managesieved,
amavisd-new, razor, pyzor, dovecot-antispam, spamassassin, fail2ban,
nginx-extras (>=1.6.2), php5-fpm, php5-ldap, php5-intl,
dnsmasq, openssl, avahi-daemon,
ssowat, metronome
Recommends: yunohost-admin,
bash-completion, rsyslog, ntp, openssh-server,
php5-gd, php5-curl, php-gettext, php5-mcrypt,
udisks-glue, unattended-upgrades,
libdbd-ldap-perl, libnet-dns-perl
Suggests: htop, vim, rsync, acpi-support-base
Conflicts: iptables-persistent
Description: YunoHost Python scripts
Python functions to manage a YunoHost instance
Description: YunoHost installation package
YunoHost aims to make self-hosting accessible to everyone.
.
This package contains YunoHost scripts and binaries to be used by the
moulinette. It allows to manage the server with a command-line tool and
an API.

1011
debian/copyright vendored

File diff suppressed because it is too large Load diff

1
debian/install vendored
View file

@ -2,6 +2,7 @@ bin/* /usr/bin/
data/actionsmap/* /usr/share/moulinette/actionsmap/
data/hooks/* /usr/share/yunohost/hooks/
data/other/* /usr/share/yunohost/yunohost-config/moulinette/
data/templates/* /usr/share/yunohost/templates/
data/apps/* /usr/share/yunohost/apps/
lib/yunohost/*.py /usr/lib/moulinette/yunohost/
locales/* /usr/lib/moulinette/yunohost/locales/

60
debian/postinst vendored
View file

@ -3,62 +3,16 @@
set -e
do_configure() {
TMP=/usr/share/yunohost/yunohost-config/moulinette
if [ ! -d /etc/yunohost ];
then
mkdir -p /etc/yunohost
fi
# Allow users to access /media directory
if [ ! -d /etc/skel/media ];
then
mkdir -p /media
ln -s /media /etc/skel/
fi
#Firewall
grep -q "UPNP:" /etc/yunohost/firewall.yml > /dev/null 2>&1
if [[ $? -eq 0 ]] || [ ! -f /etc/yunohost/firewall.yml ];
then
cp $TMP/firewall.yml /etc/yunohost/
fi
# App fetchlist
if [ -f /etc/cron.d/yunohost-applist-yunohost ];
then
sed -i "s/--no-ldap //g" /etc/cron.d/yunohost-applist-yunohost
fi
# Service list
if [ ! -f /etc/yunohost/services.yml ];
then
cp $TMP/services.yml /etc/yunohost/
fi
# Stop old API
ps aux | grep "yunohost.tac" | grep -qv grep
if [[ $? -eq 0 ]];
then
killall twistd
fi
rm -rf /var/cache/moulinette/*
update-rc.d yunohost-api defaults > /dev/null
service yunohost-api restart
# Firewall
update-rc.d yunohost-firewall defaults > /dev/null
# Reload SSOwat conf if obsolete
if [ -f /etc/yunohost/installed ];
then
yunohost firewall upnp | grep -qi "true"
if [[ $? -eq 0 ]];
then
yunohost firewall upnp enable
fi
yunohost app ssowatconf
if [ ! -f /etc/yunohost/installed ]; then
bash /usr/share/yunohost/hooks/conf_regen/01-yunohost
bash /usr/share/yunohost/hooks/conf_regen/02-ssl
bash /usr/share/yunohost/hooks/conf_regen/06-slapd
bash /usr/share/yunohost/hooks/conf_regen/15-nginx
else
yunohost service regenconf
fi
}

11
debian/preinst vendored
View file

@ -1,11 +0,0 @@
#!/bin/sh
set -e
if [ -f /etc/init.d/yunohost-api ]; then
service yunohost-api stop
# nc -zv 127.0.0.1 6787 < /dev/null 2> /dev/null
# if [[ ! $? -eq 0 ]];
# then
# exit 1
# fi
fi

2
debian/rules vendored
View file

@ -5,7 +5,7 @@
#export DH_VERBOSE=1
%:
dh $@
dh ${@} --with=systemd
override_dh_installinit:
dh_installinit --name=yunohost-api

View file

@ -1,75 +1,127 @@
#! /bin/bash
#! /bin/sh
### BEGIN INIT INFO
# Provides: yunohost-api
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop YunoHost API
# Description: Start/stop YunoHost API
# Short-Description: Manage YunoHost API Server
# Description: Manage YunoHost API Server
### END INIT INFO
DAEMON=/usr/bin/yunohost-api
set -e
DESC="YunoHost API Server"
NAME="yunohost-api"
DAEMON=/usr/bin/$NAME
DAEMON_OPTS=""
PATH=/sbin:/usr/sbin:/bin:/usr/bin
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
LOGFILE=/var/log/$NAME.log
test -x $DAEMON || exit 0
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
logger "YunoHost API: Start script executed"
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --background --make-pidfile --quiet --no-close \
--pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS >>$LOGFILE 2>&1 \
|| return 2
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --oknodo --pidfile $PIDFILE
RETVAL="$?"
sleep 1
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
# Send a SIGHUP to reload the daemon.
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
logger "YunoHost API: Starting"
log_daemon_msg "Starting API: YunoHost"
if [[ -f /etc/nginx/conf.d/openresty.conf ]];
then
DAEMON_OPTS="--no-websocket"
fi
start-stop-daemon --start --background --pidfile /var/run/yunohost-api.pid --make-pidfile \
--exec /bin/bash -- -c "$DAEMON $DAEMON_OPTS >> /var/log/yunohost.log 2>&1"
log_end_msg $?
;;
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
logger "YunoHost API: Stopping"
log_daemon_msg "Stopping API: YunoHost"
if [ -f /var/run/yunohost-api.pid ]; then
kill `cat /var/run/yunohost-api.pid` > /dev/null 2>&1
rm -f /var/run/yunohost-api.pid
fi
kill `ps aux | grep 'python /usr/bin/yunohost-api' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1
kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v stop | awk '{print $2}'` > /dev/null 2>&1
log_end_msg 0
;;
restart|force-reload)
logger "YunoHost API: Restarting"
log_daemon_msg "Restarting API: YunoHost"
if [ -f /var/run/yunohost-api.pid ]; then
kill `cat /var/run/yunohost-api.pid` > /dev/null 2>&1
rm -f /var/run/yunohost-api.pid
fi
kill `ps aux | grep 'python /usr/bin/yunohost-api' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1
kill `ps aux | grep 'yunohost-api' | grep -v grep | grep -v restart | awk '{print $2}'` > /dev/null 2>&1
kill `ps aux | grep 'yunohost.tac' | grep -v grep | awk '{print $2}'` > /dev/null 2>&1
if [[ -f /etc/nginx/conf.d/openresty.conf ]];
then
DAEMON_OPTS="--no-websocket"
fi
start-stop-daemon --start --background --pidfile /var/run/yunohost-api.pid --make-pidfile \
--exec /bin/bash -- -c "$DAEMON $DAEMON_OPTS >> /var/log/yunohost.log 2>&1"
log_end_msg $?
;;
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
logger "YunoHost API: Running"
log_daemon_msg "YunoHost API: Running"
cat /var/run/yunohost-api.pid > /dev/null 2>&1
log_end_msg $?
;;
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
reload)
log_daemon_msg "Reloading $DESC" "$NAME"
do_reload
log_end_msg $?
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
logger "YunoHost API: Invalid usage"
echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2
exit 1
;;
echo "Usage: $SCRIPTNAME {start|stop|status|restart|reload}" >&2
exit 3
;;
esac
exit 0
:

13
debian/yunohost-api.service vendored Normal file
View file

@ -0,0 +1,13 @@
[Unit]
Description=YunoHost API Server
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/yunohost-api
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=1
[Install]
WantedBy=multi-user.target

View file

@ -70,7 +70,7 @@ def app_fetchlist(url=None, name=None):
Keyword argument:
name -- Name of the list (default yunohost)
url -- URL of remote JSON list (default https://app.yunohost.org/list.json)
url -- URL of remote JSON list (default https://yunohost.org/list.json)
"""
# Create app path if not exists
@ -78,7 +78,7 @@ def app_fetchlist(url=None, name=None):
except OSError: os.makedirs(repo_path)
if url is None:
url = 'https://app.yunohost.org/list.json'
url = 'https://yunohost.org/list.json'
name = 'yunohost'
else:
if name is None:

View file

@ -36,11 +36,12 @@ from urllib import urlopen
from moulinette.core import MoulinetteError
def domain_list(auth, filter=None, limit=None, offset=None):
def domain_list(auth, raw=False, filter=None, limit=None, offset=None):
"""
List domains
Keyword argument:
raw -- Return domains as a bash-usable list instead of JSON
filter -- LDAP filter used to search
offset -- Starting number for domain fetching
limit -- Maximum number of domain fetched
@ -61,7 +62,12 @@ def domain_list(auth, filter=None, limit=None, offset=None):
if len(result) > offset and limit > 0:
for domain in result[offset:offset+limit]:
result_list.append(domain['virtualdomain'][0])
return { 'domains': result_list }
if raw:
for domain in result_list:
print domain
else:
return { 'domains': result_list }
def domain_add(auth, domain, dyndns=False):
@ -73,6 +79,8 @@ def domain_add(auth, domain, dyndns=False):
dyndns -- Subscribe to DynDNS
"""
from yunohost.service import service_regenconf
attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
try:
ip = str(urlopen('http://ip.yunohost.org').read())
@ -148,76 +156,16 @@ def domain_add(auth, domain, dyndns=False):
attr_dict['virtualdomain'] = domain
dnsmasq_config_path='/etc/dnsmasq.d'
try:
os.listdir(dnsmasq_config_path)
except OSError:
msignals.display(m18n.n('dnsmasq_isnt_installed'),
'warning')
os.makedirs(dnsmasq_config_path)
try:
with open('%s/%s' % (dnsmasq_config_path, domain)) as f: pass
except IOError as e:
zone_lines = [
'resolv-file=',
'address=/%s/%s' % (domain, ip),
'txt-record=%s,"v=spf1 mx a -all"' % domain,
'mx-host=%s,%s,5' % (domain, domain),
'srv-host=_xmpp-client._tcp.%s,%s,5222,0,5' % (domain, domain),
'srv-host=_xmpp-server._tcp.%s,%s,5269,0,5' % (domain, domain),
'srv-host=_jabber._tcp.%s,%s,5269,0,5' % (domain, domain),
]
with open('%s/%s' % (dnsmasq_config_path, domain), 'w') as zone:
for line in zone_lines:
zone.write(line + '\n')
os.system('service dnsmasq restart')
else:
msignals.display(m18n.n('domain_zone_exists'),
'warning')
# XMPP
try:
with open('/etc/metronome/conf.d/%s.cfg.lua' % domain) as f: pass
except IOError as e:
conf_lines = [
'VirtualHost "%s"' % domain,
' ssl = {',
' key = "%s/key.pem";' % ssl_domain_path,
' certificate = "%s/crt.pem";' % ssl_domain_path,
' }',
' authentication = "ldap2"',
' ldap = {',
' hostname = "localhost",',
' user = {',
' basedn = "ou=users,dc=yunohost,dc=org",',
' filter = "(&(objectClass=posixAccount)(mail=*@%s))",' % domain,
' usernamefield = "mail",',
' namefield = "cn",',
' },',
' }',
]
with open('/etc/metronome/conf.d/%s.cfg.lua' % domain, 'w') as conf:
for line in conf_lines:
conf.write(line + '\n')
os.system('mkdir -p /var/lib/metronome/%s/pep' % domain.replace('.', '%2e'))
os.system('chown -R metronome: /var/lib/metronome/')
os.system('chown -R metronome: /etc/metronome/conf.d/')
os.system('service metronome restart')
# Nginx
os.system('cp /usr/share/yunohost/yunohost-config/nginx/template.conf /etc/nginx/conf.d/%s.conf' % domain)
os.system('mkdir /etc/nginx/conf.d/%s.d/' % domain)
os.system('sed -i s/yunohost.org/%s/g /etc/nginx/conf.d/%s.conf' % (domain, domain))
os.system('service nginx reload')
if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict):
raise MoulinetteError(errno.EIO, m18n.n('domain_creation_failed'))
os.system('yunohost app ssowatconf > /dev/null 2>&1')
try:
with open('/etc/yunohost/installed', 'r') as f:
service_regenconf(service='nginx')
service_regenconf(service='metronome')
service_regenconf(service='dnsmasq')
os.system('yunohost app ssowatconf > /dev/null 2>&1')
except IOError: pass
except:
# Force domain removal silently
try: domain_remove(auth, domain, True)
@ -236,6 +184,8 @@ def domain_remove(auth, domain, force=False):
force -- Force the domain removal
"""
from yunohost.service import service_regenconf
if not force and domain not in domain_list(auth)['domains']:
raise MoulinetteError(errno.EINVAL, m18n.n('domain_unknown'))
@ -252,24 +202,13 @@ def domain_remove(auth, domain, force=False):
m18n.n('domain_uninstall_app_first'))
if auth.remove('virtualdomain=' + domain + ',ou=domains') or force:
command_list = [
'rm -rf /etc/yunohost/certs/%s' % domain,
'rm -f /etc/dnsmasq.d/%s' % domain,
'rm -rf /var/lib/metronome/%s' % domain.replace('.', '%2e'),
'rm -f /etc/metronome/conf.d/%s.cfg.lua' % domain,
'rm -rf /etc/nginx/conf.d/%s.d' % domain,
'rm -f /etc/nginx/conf.d/%s.conf' % domain,
]
for command in command_list:
if os.system(command) != 0:
msignals.display(m18n.n('path_removal_failed', command[7:]),
'warning')
os.system('rm -rf /etc/yunohost/certs/%s' % domain)
else:
raise MoulinetteError(errno.EIO, m18n.n('domain_deletion_failed'))
service_regenconf(service='nginx')
service_regenconf(service='metronome')
service_regenconf(service='dnsmasq')
os.system('yunohost app ssowatconf > /dev/null 2>&1')
os.system('service nginx reload')
os.system('service dnsmasq restart')
os.system('service metronome restart')
msignals.display(m18n.n('domain_deleted'), 'success')

View file

@ -184,8 +184,19 @@ def hook_callback(action, hooks=[], args=None):
else:
hooks_names = hook_list(action, list_by='name',
show_info=True)['hooks']
# Iterate over given hooks names list
# Add similar hooks to the list
# For example: Having a 16-postfix hook in the list will execute a
# xx-postfix_dkim as well
all_hooks = []
for n in hooks:
for key in hooks_names.keys():
if key == n or key.startswith("%s_" % n) \
and key not in all_hooks:
all_hooks.append(key)
# Iterate over given hooks names list
for n in all_hooks:
try:
hl = hooks_names[n]
except KeyError:

View file

@ -23,14 +23,26 @@
Manage services
"""
import os
import time
import yaml
import glob
import subprocess
import errno
import os.path
import shutil
import difflib
import hashlib
from moulinette.core import MoulinetteError
template_dir = os.getenv(
'YUNOHOST_TEMPLATE_DIR',
'/usr/share/yunohost/templates'
)
conf_backup_dir = os.getenv(
'YUNOHOST_CONF_BACKUP_DIR',
'/home/yunohost.backup/conffiles'
)
def service_add(name, status=None, log=None, runlevel=None):
"""
@ -187,7 +199,8 @@ def service_status(names=[]):
m18n.n('service_unknown', name))
status = None
if services[name]['status'] == 'service':
if 'status' not in services[name] or \
services[name]['status'] == 'service':
status = 'service %s status' % name
else:
status = str(services[name]['status'])
@ -257,9 +270,30 @@ def service_log(name, number=50):
return result
def service_regenconf(service=None, force=False):
"""
Regenerate the configuration file(s) for a service and compare the result
with the existing configuration file.
Prints the differences between files if any.
Keyword argument:
service -- Regenerate configuration for a specfic service
force -- Override the current configuration with the newly generated
one, even if it has been modified
"""
from yunohost.hook import hook_callback
if service is not None:
hook_callback('conf_regen', [service], args=[force])
else:
hook_callback('conf_regen', args=[force])
msignals.display(m18n.n('services_configured'), 'success')
def _run_service_command(action, service):
"""
Run services management command (start, stop, enable, disable)
Run services management command (start, stop, enable, disable, restart, reload)
Keyword argument:
action -- Action to perform
@ -271,7 +305,7 @@ def _run_service_command(action, service):
service))
cmd = None
if action in ['start', 'stop']:
if action in ['start', 'stop', 'restart', 'reload']:
cmd = 'service %s %s' % (service, action)
elif action in ['enable', 'disable']:
arg = 'defaults' if action == 'enable' else 'remove'
@ -302,6 +336,7 @@ def _get_services():
else:
return services
def _save_services(services):
"""
Save managed services to files
@ -314,6 +349,7 @@ def _save_services(services):
with open('/etc/yunohost/services.yml', 'w') as f:
yaml.safe_dump(services, f, default_flow_style=False)
def _tail(file, n, offset=None):
"""
Reads a n lines from f with an offset of offset lines. The return
@ -340,3 +376,185 @@ def _tail(file, n, offset=None):
avg_line_length *= 1.3
except IOError: return []
def _get_diff(string, filename):
"""
Show differences between a string and a file's content
Keyword argument:
string -- The string
filename -- The file to compare with
"""
try:
with open(filename, 'r') as f:
file_lines = f.readlines()
string = string + '\n'
new_lines = string.splitlines(True)
while '\n' == file_lines[-1]:
del file_lines[-1]
return difflib.unified_diff(file_lines, new_lines)
except IOError: return []
def _hash(filename):
"""
Calculate a MD5 hash of a file
Keyword argument:
filename -- The file to hash
"""
hasher = hashlib.md5()
try:
with open(filename, 'rb') as f:
buf = f.read()
hasher.update(buf)
return hasher.hexdigest()
except IOError:
return 'no hash yet'
def service_saferemove(service, conf_file, force=False):
"""
Check if the specific file has been modified before removing it.
Backup the file in /home/yunohost.backup
Keyword argument:
service -- Service name of the file to delete
conf_file -- The file to write
force -- Force file deletion
"""
deleted = False
services = _get_services()
if not os.path.exists(conf_file):
try:
del services[service]['conffiles'][conf_file]
except KeyError: pass
return True
# Backup existing file
date = time.strftime("%Y%m%d.%H%M%S")
conf_backup_file = conf_backup_dir + conf_file +'-'+ date
process = subprocess.Popen(
['install', '-D', conf_file, conf_backup_file]
)
process.wait()
# Retrieve hashes
if not 'conffiles' in services[service]:
services[service]['conffiles'] = {}
if conf_file in services[service]['conffiles']:
previous_hash = services[service]['conffiles'][conf_file]
else:
previous_hash = 'no hash yet'
current_hash = _hash(conf_file)
# Handle conflicts
if force or previous_hash == current_hash:
os.remove(conf_file)
try:
del services[service]['conffiles'][conf_file]
except KeyError: pass
deleted = True
else:
services[service]['conffiles'][conf_file] = previous_hash
os.remove(conf_backup_file)
if os.isatty(1) and \
(len(previous_hash) == 32 or previous_hash[-32:] != current_hash):
msignals.display(
m18n.n('service_configuration_changed', conf_file),
'warning'
)
_save_services(services)
return deleted
def service_safecopy(service, new_conf_file, conf_file, force=False):
"""
Check if the specific file has been modified and display differences.
Stores the file hash in the services.yml file
Keyword argument:
service -- Service name attached to the conf file
new_conf_file -- Path to the desired conf file
conf_file -- Path to the targeted conf file
force -- Force file overriding
"""
regenerated = False
services = _get_services()
if not os.path.exists(new_conf_file):
raise MoulinetteError(errno.EIO, m18n.n('no_such_conf_file', new_conf_file))
with open(new_conf_file, 'r') as f:
new_conf = ''.join(f.readlines()).rstrip()
# Backup existing file
date = time.strftime("%Y%m%d.%H%M%S")
conf_backup_file = conf_backup_dir + conf_file +'-'+ date
if os.path.exists(conf_file):
process = subprocess.Popen(
['install', '-D', conf_file, conf_backup_file]
)
process.wait()
else:
msignals.display(m18n.n('service_add_configuration', conf_file),
'info')
# Add the service if it does not exist
if service not in services.keys():
services[service] = {}
# Retrieve hashes
if not 'conffiles' in services[service]:
services[service]['conffiles'] = {}
if conf_file in services[service]['conffiles']:
previous_hash = services[service]['conffiles'][conf_file]
else:
previous_hash = 'no hash yet'
current_hash = _hash(conf_file)
diff = list(_get_diff(new_conf, conf_file))
# Handle conflicts
if force or previous_hash == current_hash:
with open(conf_file, 'w') as f: f.write(new_conf)
new_hash = _hash(conf_file)
if previous_hash != new_hash:
regenerated = True
elif len(diff) == 0:
new_hash = _hash(conf_file)
else:
new_hash = previous_hash
if (len(previous_hash) == 32 or previous_hash[-32:] != current_hash):
msignals.display(
m18n.n('service_configuration_conflict', conf_file),
'warning'
)
print('\n' + conf_file)
for line in diff:
print(line.strip())
print('')
# Remove the backup file if the configuration has not changed
if new_hash == previous_hash:
try:
os.remove(conf_backup_file)
except OSError: pass
services[service]['conffiles'][conf_file] = new_hash
_save_services(services)
return regenerated

View file

@ -106,6 +106,7 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False):
"""
from yunohost.domain import domain_add, domain_list
from yunohost.dyndns import dyndns_subscribe
from yunohost.service import service_regenconf
if not old_domain:
with open('/etc/yunohost/current_host', 'r') as f:
@ -119,71 +120,13 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False):
if new_domain not in domain_list(auth)['domains']:
domain_add(auth, new_domain)
config_files = [
'/etc/postfix/main.cf',
'/etc/metronome/metronome.cfg.lua',
'/etc/dovecot/dovecot.conf',
'/usr/share/yunohost/yunohost-config/others/startup',
'/etc/amavis/conf.d/05-node_id',
'/etc/amavis/conf.d/50-user'
]
config_dir = []
for dir in config_dir:
for file in os.listdir(dir):
config_files.append(dir + '/' + file)
for file in config_files:
with open(file, "r") as sources:
lines = sources.readlines()
with open(file, "w") as sources:
for line in lines:
sources.write(re.sub(r''+ old_domain +'', new_domain, line))
## Update DNS zone file for old and new domains
main_subdomains = ['pubsub', 'muc', 'vjud']
try:
with open('/var/lib/bind/%s.zone' % old_domain, 'r') as f:
old_zone = f.read()
except IOError:
pass
else:
# Remove unneeded subdomains entries
for sub in main_subdomains:
old_zone = re.sub(
r'^({sub}.{domain}.|{sub})[\ \t]+(IN).*$[\n]?'.format(
sub=sub, domain=old_domain),
'', old_zone, 1, re.MULTILINE)
with open('/var/lib/bind/%s.zone' % old_domain, 'w') as f:
f.write(old_zone)
try:
with open('/var/lib/bind/%s.zone' % new_domain, 'r') as f:
new_zone = f.read()
except IOError:
msignals.display(m18n.n('domain_zone_not_found', new_domain), 'warning')
else:
# Add main subdomains entries
for sub in main_subdomains:
new_zone += '{sub} IN CNAME {domain}.\n'.format(
sub=sub, domain=new_domain)
with open('/var/lib/bind/%s.zone' % new_domain, 'w') as f:
f.write(new_zone)
os.system('rm /etc/ssl/private/yunohost_key.pem')
os.system('rm /etc/ssl/certs/yunohost_crt.pem')
command_list = [
'rm -f /etc/nginx/conf.d/%s.d/yunohost_local.conf' % old_domain,
'cp /usr/share/yunohost/yunohost-config/nginx/yunohost_local.conf /etc/nginx/conf.d/%s.d/' % new_domain,
'ln -s /etc/yunohost/certs/%s/key.pem /etc/ssl/private/yunohost_key.pem' % new_domain,
'ln -s /etc/yunohost/certs/%s/crt.pem /etc/ssl/certs/yunohost_crt.pem' % new_domain,
'echo %s > /etc/yunohost/current_host' % new_domain,
'service metronome restart',
'service postfix restart',
'service dovecot restart',
'service amavis restart',
'service nginx restart',
]
for command in command_list:
@ -202,6 +145,11 @@ def tools_maindomain(auth, old_domain=None, new_domain=None, dyndns=False):
if dyndomain in dyndomains:
dyndns_subscribe(domain=new_domain)
try:
with open('/etc/yunohost/installed', 'r') as f:
service_regenconf()
except IOError: pass
msignals.display(m18n.n('maindomain_changed'), 'success')
@ -219,6 +167,7 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
from yunohost.app import app_ssowatconf
from yunohost.firewall import firewall_upnp, firewall_reload
from yunohost.service import service_regenconf
dyndns = not ignore_dyndns
@ -327,6 +276,8 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
os.system('touch /etc/yunohost/installed')
service_regenconf(force=True)
msignals.display(m18n.n('yunohost_configured'), 'success')