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 authenticate: all
authenticator: ldap-anonymous authenticator: ldap-anonymous
arguments: arguments:
-r:
full: --raw
help: Return domains as a bash-usable list instead of JSON
action: store_true
-f: -f:
full: --filter full: --filter
help: LDAP filter used to search help: LDAP filter used to search
@ -260,6 +264,7 @@ domain:
action_help: Create a custom domain action_help: Create a custom domain
api: POST /domains api: POST /domains
configuration: configuration:
lock: false
authenticate: all authenticate: all
arguments: arguments:
domain: domain:
@ -278,6 +283,7 @@ domain:
action_help: Delete domains action_help: Delete domains
api: DELETE /domains/<domain> api: DELETE /domains/<domain>
configuration: configuration:
lock: false
authenticate: all authenticate: all
arguments: arguments:
domain: domain:
@ -913,6 +919,63 @@ service:
default: 50 default: 50
type: int 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 # # 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: amavis:
status: service status: service
log: /var/log/mail.log 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 Source: yunohost
Section: net Section: utils
Priority: extra Priority: extra
Maintainer: Jérôme Lebleu <jerome.lebleu@mailoo.org> Maintainer: YunoHost Contributors <contrib@yunohost.org>
Build-Depends: debhelper (>=8.0.0) Build-Depends: debhelper (>=9), dh-systemd
Standards-Version: 3.9.4 Standards-Version: 3.9.6
Homepage: https://yunohost.org/ Homepage: https://yunohost.org/
Package: moulinette-yunohost Package: yunohost
Architecture: all Architecture: all
Depends: moulinette (>= 2.2.1), Depends: ${misc:Depends}, ${shlibs:Depends},
moulinette (>= 2.2.1),
python-psutil, python-psutil,
python-requests, python-requests,
glances, glances,
@ -25,6 +26,23 @@ Depends: moulinette (>= 2.2.1),
git-core, git-core,
curl, curl,
mariadb-server | mysql-server, php5-mysql | php5-mysqlnd 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 Conflicts: iptables-persistent
Description: YunoHost Python scripts Description: YunoHost installation package
Python functions to manage a YunoHost instance 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/actionsmap/* /usr/share/moulinette/actionsmap/
data/hooks/* /usr/share/yunohost/hooks/ data/hooks/* /usr/share/yunohost/hooks/
data/other/* /usr/share/yunohost/yunohost-config/moulinette/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/
data/templates/* /usr/share/yunohost/templates/
data/apps/* /usr/share/yunohost/apps/ data/apps/* /usr/share/yunohost/apps/
lib/yunohost/*.py /usr/lib/moulinette/yunohost/ lib/yunohost/*.py /usr/lib/moulinette/yunohost/
locales/* /usr/lib/moulinette/yunohost/locales/ locales/* /usr/lib/moulinette/yunohost/locales/

60
debian/postinst vendored
View file

@ -3,62 +3,16 @@
set -e set -e
do_configure() { 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/* rm -rf /var/cache/moulinette/*
update-rc.d yunohost-api defaults > /dev/null
service yunohost-api restart service yunohost-api restart
# Firewall if [ ! -f /etc/yunohost/installed ]; then
update-rc.d yunohost-firewall defaults > /dev/null bash /usr/share/yunohost/hooks/conf_regen/01-yunohost
bash /usr/share/yunohost/hooks/conf_regen/02-ssl
# Reload SSOwat conf if obsolete bash /usr/share/yunohost/hooks/conf_regen/06-slapd
if [ -f /etc/yunohost/installed ]; bash /usr/share/yunohost/hooks/conf_regen/15-nginx
then else
yunohost firewall upnp | grep -qi "true" yunohost service regenconf
if [[ $? -eq 0 ]];
then
yunohost firewall upnp enable
fi
yunohost app ssowatconf
fi 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 #export DH_VERBOSE=1
%: %:
dh $@ dh ${@} --with=systemd
override_dh_installinit: override_dh_installinit:
dh_installinit --name=yunohost-api dh_installinit --name=yunohost-api

View file

@ -1,75 +1,127 @@
#! /bin/bash #! /bin/sh
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: yunohost-api # Provides: yunohost-api
# Required-Start: $local_fs $remote_fs $network $syslog # Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Start/stop YunoHost API # Short-Description: Manage YunoHost API Server
# Description: Start/stop YunoHost API # Description: Manage YunoHost API Server
### END INIT INFO ### END INIT INFO
DAEMON=/usr/bin/yunohost-api set -e
DESC="YunoHost API Server"
NAME="yunohost-api"
DAEMON=/usr/bin/$NAME
DAEMON_OPTS="" 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 . /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 case "$1" in
start) start)
logger "YunoHost API: Starting" [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
log_daemon_msg "Starting API: YunoHost" do_start
if [[ -f /etc/nginx/conf.d/openresty.conf ]]; case "$?" in
then 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
DAEMON_OPTS="--no-websocket" 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
fi esac
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 $?
;;
stop) stop)
logger "YunoHost API: Stopping" [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
log_daemon_msg "Stopping API: YunoHost" do_stop
if [ -f /var/run/yunohost-api.pid ]; then case "$?" in
kill `cat /var/run/yunohost-api.pid` > /dev/null 2>&1 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
rm -f /var/run/yunohost-api.pid 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
fi esac
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 $?
;;
status) status)
logger "YunoHost API: Running" status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
log_daemon_msg "YunoHost API: Running" ;;
cat /var/run/yunohost-api.pid > /dev/null 2>&1 reload)
log_end_msg $? 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: $SCRIPTNAME {start|stop|status|restart|reload}" >&2
echo "Usage: /etc/init.d/yunohost-api {start|stop|restart|force-reload|status}" >&2 exit 3
exit 1 ;;
;;
esac 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: Keyword argument:
name -- Name of the list (default yunohost) 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 # Create app path if not exists
@ -78,7 +78,7 @@ def app_fetchlist(url=None, name=None):
except OSError: os.makedirs(repo_path) except OSError: os.makedirs(repo_path)
if url is None: if url is None:
url = 'https://app.yunohost.org/list.json' url = 'https://yunohost.org/list.json'
name = 'yunohost' name = 'yunohost'
else: else:
if name is None: if name is None:

View file

@ -36,11 +36,12 @@ from urllib import urlopen
from moulinette.core import MoulinetteError 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 List domains
Keyword argument: Keyword argument:
raw -- Return domains as a bash-usable list instead of JSON
filter -- LDAP filter used to search filter -- LDAP filter used to search
offset -- Starting number for domain fetching offset -- Starting number for domain fetching
limit -- Maximum number of domain fetched 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: if len(result) > offset and limit > 0:
for domain in result[offset:offset+limit]: for domain in result[offset:offset+limit]:
result_list.append(domain['virtualdomain'][0]) 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): def domain_add(auth, domain, dyndns=False):
@ -73,6 +79,8 @@ def domain_add(auth, domain, dyndns=False):
dyndns -- Subscribe to DynDNS dyndns -- Subscribe to DynDNS
""" """
from yunohost.service import service_regenconf
attr_dict = { 'objectClass' : ['mailDomain', 'top'] } attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
try: try:
ip = str(urlopen('http://ip.yunohost.org').read()) ip = str(urlopen('http://ip.yunohost.org').read())
@ -148,76 +156,16 @@ def domain_add(auth, domain, dyndns=False):
attr_dict['virtualdomain'] = domain 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): if not auth.add('virtualdomain=%s,ou=domains' % domain, attr_dict):
raise MoulinetteError(errno.EIO, m18n.n('domain_creation_failed')) 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: except:
# Force domain removal silently # Force domain removal silently
try: domain_remove(auth, domain, True) try: domain_remove(auth, domain, True)
@ -236,6 +184,8 @@ def domain_remove(auth, domain, force=False):
force -- Force the domain removal force -- Force the domain removal
""" """
from yunohost.service import service_regenconf
if not force and domain not in domain_list(auth)['domains']: if not force and domain not in domain_list(auth)['domains']:
raise MoulinetteError(errno.EINVAL, m18n.n('domain_unknown')) 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')) m18n.n('domain_uninstall_app_first'))
if auth.remove('virtualdomain=' + domain + ',ou=domains') or force: if auth.remove('virtualdomain=' + domain + ',ou=domains') or force:
command_list = [ os.system('rm -rf /etc/yunohost/certs/%s' % domain)
'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')
else: else:
raise MoulinetteError(errno.EIO, m18n.n('domain_deletion_failed')) 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('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') msignals.display(m18n.n('domain_deleted'), 'success')

View file

@ -184,8 +184,19 @@ def hook_callback(action, hooks=[], args=None):
else: else:
hooks_names = hook_list(action, list_by='name', hooks_names = hook_list(action, list_by='name',
show_info=True)['hooks'] 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 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: try:
hl = hooks_names[n] hl = hooks_names[n]
except KeyError: except KeyError:

View file

@ -23,14 +23,26 @@
Manage services Manage services
""" """
import os
import time
import yaml import yaml
import glob import glob
import subprocess import subprocess
import errno import errno
import os.path import shutil
import difflib
import hashlib
from moulinette.core import MoulinetteError 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): def service_add(name, status=None, log=None, runlevel=None):
""" """
@ -187,7 +199,8 @@ def service_status(names=[]):
m18n.n('service_unknown', name)) m18n.n('service_unknown', name))
status = None status = None
if services[name]['status'] == 'service': if 'status' not in services[name] or \
services[name]['status'] == 'service':
status = 'service %s status' % name status = 'service %s status' % name
else: else:
status = str(services[name]['status']) status = str(services[name]['status'])
@ -257,9 +270,30 @@ def service_log(name, number=50):
return result 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): 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: Keyword argument:
action -- Action to perform action -- Action to perform
@ -271,7 +305,7 @@ def _run_service_command(action, service):
service)) service))
cmd = None cmd = None
if action in ['start', 'stop']: if action in ['start', 'stop', 'restart', 'reload']:
cmd = 'service %s %s' % (service, action) cmd = 'service %s %s' % (service, action)
elif action in ['enable', 'disable']: elif action in ['enable', 'disable']:
arg = 'defaults' if action == 'enable' else 'remove' arg = 'defaults' if action == 'enable' else 'remove'
@ -302,6 +336,7 @@ def _get_services():
else: else:
return services return services
def _save_services(services): def _save_services(services):
""" """
Save managed services to files Save managed services to files
@ -314,6 +349,7 @@ def _save_services(services):
with open('/etc/yunohost/services.yml', 'w') as f: with open('/etc/yunohost/services.yml', 'w') as f:
yaml.safe_dump(services, f, default_flow_style=False) yaml.safe_dump(services, f, default_flow_style=False)
def _tail(file, n, offset=None): def _tail(file, n, offset=None):
""" """
Reads a n lines from f with an offset of offset lines. The return 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 avg_line_length *= 1.3
except IOError: return [] 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.domain import domain_add, domain_list
from yunohost.dyndns import dyndns_subscribe from yunohost.dyndns import dyndns_subscribe
from yunohost.service import service_regenconf
if not old_domain: if not old_domain:
with open('/etc/yunohost/current_host', 'r') as f: 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']: if new_domain not in domain_list(auth)['domains']:
domain_add(auth, new_domain) 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/private/yunohost_key.pem')
os.system('rm /etc/ssl/certs/yunohost_crt.pem') os.system('rm /etc/ssl/certs/yunohost_crt.pem')
command_list = [ 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/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, 'ln -s /etc/yunohost/certs/%s/crt.pem /etc/ssl/certs/yunohost_crt.pem' % new_domain,
'echo %s > /etc/yunohost/current_host' % 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: 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: if dyndomain in dyndomains:
dyndns_subscribe(domain=new_domain) 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') 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.app import app_ssowatconf
from yunohost.firewall import firewall_upnp, firewall_reload from yunohost.firewall import firewall_upnp, firewall_reload
from yunohost.service import service_regenconf
dyndns = not ignore_dyndns dyndns = not ignore_dyndns
@ -327,6 +276,8 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
os.system('touch /etc/yunohost/installed') os.system('touch /etc/yunohost/installed')
service_regenconf(force=True)
msignals.display(m18n.n('yunohost_configured'), 'success') msignals.display(m18n.n('yunohost_configured'), 'success')