SMEServer - Building your contrib
https://wiki.koozali.org/Building_Your_Contrib
This how-to intend to give you a tour of what you need with some usefull tmeplates to build you own contrib on SME10 with last php-fpm, httpd 2.4, core backup integration and systemd usage Template:WIP box
Contents
Architecture
SPEC file
<syntaxhighlight lang="spec"> %define name foo %define version 3.6.431 %define release 1 Summary: foo is a helpdesk system Name: %{name} Version: %{version} Release: %{release}%{?dist} Distribution: SME Server License: GNU GPL version 2 URL: http://www.fooweb.com Group: SMEserver/addon
Source: foo-3.6.431.tar.gz Packager: Stephen Foo <support@foo.net> BuildArchitectures: noarch BuildRoot: /var/tmp/%{name}-%{version} BuildRequires: e-smith-devtools Requires: e-smith-release >= 7.0 AutoReqProv: no
%description http://foo.org/ foo is a helpdesk system
%changelog
- Thu Sep 13 2007 Stephen Foo <support@foo.net> 3.6.431-1
- initial release - builds from unchanged .tar.gz
%prep %setup -c -n %{name}
%build perl createlink
%install rm -rf $RPM_BUILD_ROOT (cd root ; find . -depth -print | cpio -dump $RPM_BUILD_ROOT) rm -f %{name}-%{version}-filelist /sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
--dir '/opt/foo/tempdir/' 'attr(775,www,www)' \ --file '/opt/foo/logo.gif' 'attr(660,www,www)' \ --ignoredir '/opt/foo' \ --dir /var/log/foo 'attr(0755,root,root)' \ --dir /var/log/php/foo 'attr(0755,www,www)' \ --dir /var/lib/php/foo 'attr(0755,www,www)' \ --dir /var/lib/php/foo/tmp 'attr(0755,www,www)' \ --dir /var/lib/php/foo/opcache 'attr(0755,www,www)' \ --dir /var/lib/php/foo/session 'attr(0755,www,www)' \
> %{name}-%{version}-filelist
%clean cd .. rm -rf %{name}
%files -f %{name}-%{version}-filelist %defattr(-,root,root) </syntaxhighlight>
Createlinks
<syntaxhighlight lang="perl">
- !/usr/bin/perl
use strict; use esmith::Build::CreateLinks qw(:all);
my $pkg= "smeserver-mycontrib"; my $event = "${pkg}-update";
event_actions($event, qw(
myfoo 05 systemd-default 88 systemd-reload 89
));
event_templates($event, qw( /etc/e-smith/db/configuration/migrate/80mycontrib /etc/httpd/conf/httpd.conf /etc/opt/remi/php80/php-fpm.d/www.conf /opt/foo/foo.conf ));
event_services($event, qw(
php80-php-fpm restart httpd-e-smith restart mysql.init restart mycontrib restart
));
use esmith::Build::Backup qw(:all); backup_includes($pkg, qw( /opt/foo/ ));
</syntaxhighlight>
Configuration DB
In order to have a service to start using systemd, you need it to be defined in the e-smith configuration db, here is the bare minimum:<syntaxhighlight lang="bash"> echo "service" > smeserver-mycontrib-1.0/root/etc/e-smith/db/configuration/defaults/mycontrib/type echo "enabled" > smeserver-mycontrib-1.0/root/etc/e-smith/db/configuration/defaults/mycontrib/status
</syntaxhighlight>You might also need to add a TCPPort or TCPPorts property if needed to open ports in firewall, and also an access property to make access private or public (default is localhost). You can also populate any dedicated property you would need for your own use.
Mariadb myslq init
generate default user, password and db for your app
create the following file to generate the default password dbname and dbuser
smeserver-mycontrib-1.0/root/etc/e-smith/db/configuration/migrate/80mycontrib<syntaxhighlight lang="perl"> {
use MIME::Base64 qw(encode_base64);
my $rec = $DB->get('mycontrib') || $DB->new_record('mycontrib', {type => 'service'});
my $pw = $rec->prop('DbPassword'); return "" if $pw; $pw = MIME::Base64::encode(int( (1000000000000000) * rand() )); chomp($pw); $rec->set_prop('DbPassword', "$pw" );
}
</syntaxhighlight>and the following <syntaxhighlight lang="bash"> echo "mycontrib" > smeserver-mycontrib-1.0/root/etc/e-smith/db/configuration/defaults/mycontrib/DbName echo "mycontrib" > smeserver-mycontrib-1.0/root/etc/e-smith/db/configuration/defaults/mycontrib/DbUser
</syntaxhighlight>
create and populate your db
Then, create a file in smeserver-mycontrib-1.0/root/etc/e-smith/templates/etc/e-smith/sql/init/80mycontrib.
This content will generate a new user and db into your mariadb server, when expanding the template and restarting service mysql.init <syntaxhighlight lang="perl"> {
my $db = $mycontrib{DbName} || 'mycontrib'; my $user = $mycontrib{DbUser} || 'mycontrib'; my $pass = $mycontrib{DbPassword} || 'changeme'; $OUT .= <<END
- ! /bin/sh
if [ -d /var/lib/mysql/$db ]; then exit fi /usr/bin/mysql <<EOF CREATE DATABASE $db DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; use $db; #Insert application specific command to create database structure
use mysql; GRANT ALL PRIVILEGES ON $db.* TO $user\@localhost IDENTIFIED BY '$pass'; flush privileges;
EOF END }
</syntaxhighlight>You can also add some line in there to populate the content of the database using a mysql dump. Pay attention to make it not to overwrite existing data ;)
Systemd
all you need to have your service to start is
- a configuration db key foo of type service with status enabled
- a dropin file as this one
smeserver-mycontrib-1.0/root/usr/lib/systemd/system/foo.service.d/50koozali.conf<syntaxhighlight lang="yaml"> [Service]
- first we reset the ExecStartPre, if we do not want the initial lines to be executed
ExecStartPre=
- our needs
ExecStartPre=-/sbin/e-smith/service-status foo ExecStartPre=-/sbin/e-smith/expand-template /opt/foo/foo.conf
Restart=always [Install]
- so it start on boot
WantedBy=sme-server.target
</syntaxhighlight>
PHP-FPM
all you need is to add and improve this fragment .
What version of php it will be used against depends on the value you set on the line "if ($PHP_VERSION eq '80'){". This template is called for every version of php using the magic of template.metadata.
smeserver-foo-1.0/root/etc/e-smith/templates/etc/php-fpm.d/www.conf/15foo<syntaxhighlight lang="perl"> {
if ($PHP_VERSION eq '80'){
if (($foo{'status'} || 'disabled') eq 'enabled'){ my $max_upload_size = ($foo{MaxUploadSize} || '4096'); $max_upload_size .= 'M' if ($max_upload_size =~ m/^\d+$/); my $memory_limit = ($foo{MemoryLimit} || '500M'); $memory_limit .= 'M' if ($memory_limit =~ m/^\d+$/); my $open_basedir= $foo{PHPBaseDir} || ; $open_basedir = "/opt/foo/html/:/var/log/foo/:/var/lib/php/foo:$open_basedir"; my $id = 'foo'; my $max_children = $foo{'PHPmaxChildren'} || 20; my $min_spare_servers = $foo{'PHPminServers'} || 4; my $start_servers = $foo{'PHPstartServers'} || 6; my $max_spare_servers = $foo{'PHPmaxServers'} || 8; my $max_requests = $foo{'PHPmaxRequests'} || 1000; $min_spare_servers = ( $min_spare_servers > $max_spare_servers ) ? printf("%.0f",$max_spare_servers/2) : $min_spare_servers; $start_servers = ( $start_servers > $max_spare_servers ) ? printf("%.0f", $max_spare_servers /2 + $min_spare_servers/2 ) : $start_servers;
$OUT .=<<_EOF;
[php$PHP_VERSION-$id] user = www group = www listen.owner = root listen.group = www listen.mode = 0660 listen = /var/run/php-fpm/php$PHP_VERSION-$id.sock pm = dynamic pm.max_children = $max_children pm.start_servers = $start_servers pm.min_spare_servers = $min_spare_servers pm.max_spare_servers = $max_spare_servers pm.max_requests = $max_requests php_admin_value[session.save_path] = /var/lib/php/$id/session php_admin_value[session.gc_maxlifetime] = 86400 php_admin_value[opcache.file_cache] = /var/lib/php/$id/opcache php_admin_value[upload_tmp_dir] = /var/lib/php/$id/tmp php_admin_value[error_log] = /var/log/php/$id/error.log slowlog = /var/log/php/foo/slow.log php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f php@{ $DomainName } php_admin_flag[display_errors] = off php_admin_flag[log_errors] = on php_admin_value[error_log] = syslog php_admin_value[memory_limit] = $memory_limit php_admin_value[max_execution_time] = 3600 php_admin_value[post_max_size] = $max_upload_size php_admin_value[upload_max_filesize] = $max_upload_size php_admin_value[disable_functions] = system, show_source, symlink, dl, passthru, phpinfo, escapeshellarg, escapeshellcmd php_admin_value[open_basedir] = $open_basedir php_admin_flag[allow_url_fopen] = on php_admin_flag[file_uploads] = on php_admin_flag[session.cookie_httponly] = on php_admin_flag[allow_url_include] = off php_admin_value[session.save_handler] = files php_admin_flag[output_buffering] = off
_EOF
} else{ $OUT .= '; foo is disabled'; }
} }
</syntaxhighlight>you will also need the specific files created and accessible by www, that is done in the spec file for the permission and you need also to create them <syntaxhighlight lang="bash"> mkdir -p smeserver-foo-1.0/root/var/lib/php/foo/{session,tmp,opcache} mkdir -p smeserver-foo-1.0/root/var/log/php/foo mkdir -p smeserver-foo-1.0/root/var/log/foo </syntaxhighlight>
Apache httpd
you will need to create a template fragment for your contrib in order to get it displayed by the httpd server. There are three major situations:
php-fpm using a subdir
<syntaxhighlight lang="perl"> {
$allow = ($access eq 'public')?'all granted':"ip $localAccess $externalSSLAccess";
}
Alias /nextcloud /usr/share/nextcloud
<Directory "/usr/share/nextcloud"> Options +FollowSymLinks AllowOverride All <FilesMatch \.php$> SetHandler "proxy:unix:/var/run/php-fpm/php81-mycontrib.sock|fcgi://localhost" </FilesMatch> Require {$allow} SetEnv HOME /usr/share/nextcloud SetEnv HTTP_HOME /usr/share/nextcloud SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 </Directory> <Directory "/home/e-smith/files/nextcloud/data/"> # just in case if .htaccess gets disabled Require all denied </Directory>
</syntaxhighlight>
php-fpm using a dedicated virtualhost
You can simply use the virtualhost template subfolder WebAppVirtualHost/ or create your own. If you want to create your own check the content of /etc/e-smith/templates/etc/httpd/conf/httpd.conf/WebAppVirtualHost and adapt it to your needs with a new path
Then the admin after installing the contrib can set the dedicated virtualhost using the command <syntaxhighlight lang="bash"> db domains set mycontrib.mydomain.com domain Content Primary Description mycontrib DocumentRoot /usr/share/mycontrib Nameservers internet RequireSSL enabled TemplatePath WebAppVirtualHost letsencryptSSLcert enabled </syntaxhighlight>
proxypass to a port
You can simply use the proxypass directive see SME Server:Documentation:ProxyPass, either using a domain or an URI / location.
You can also create your own template fragment like 99madsonic<syntaxhighlight lang="perl"> {
$OUT .= " # static html, js, images, etc. served from coolwsd\n"; $OUT .= " # browser is the client part of LibreOffice Online\n"; $OUT .= " ProxyPass /browser http://127.0.0.1:9980/browser retry=0\n"; $OUT .= " ProxyPassReverse /browser http://127.0.0.1:9980/browser\n";
$OUT .= " # WOPI discovery URL\n"; $OUT .= " ProxyPass /hosting/discovery http://127.0.0.1:9980/hosting/discovery retry=0\n"; $OUT .= " ProxyPassReverse /hosting/discovery http://127.0.0.1:9980/hosting/discovery\n";
}
</syntaxhighlight>
Assemble and build
Final step is to assemble your archive content, and build a rpm. This is quite similar to what you can see in Package Modification or Package Import