SMEServer - Building your contrib

From Realm Business Systems Ltd
Jump to: navigation, search

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

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

  1. wget http://www.fooweb.com/downloads/foo-3.6.431.tar.gz

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">

  1. !/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
  1. ! /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

  1. a configuration db key foo of type service with status enabled
  2. a dropin file as this one

smeserver-mycontrib-1.0/root/usr/lib/systemd/system/foo.service.d/50koozali.conf<syntaxhighlight lang="yaml"> [Service]

  1. first we reset the ExecStartPre, if we do not want the initial lines to be executed

ExecStartPre=

  1. our needs

ExecStartPre=-/sbin/e-smith/service-status foo ExecStartPre=-/sbin/e-smith/expand-template /opt/foo/foo.conf

Restart=always [Install]

  1. 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