Building Your Contrib

From SME Server
Jump to navigationJump to search

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

Warning.png Work in Progress:
Unnilennium has marked this page as a Work in Progress. The contents off this page may be in flux, please have a look at this page history the to see list of changes.


Architecture

SPEC file

%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
#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)

Createlinks

#!/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/
));

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:

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

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

{
   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" );
}

and the following

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

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

{
   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
}

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

[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

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

{

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';
  }
}
}

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

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

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

{
  $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>

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

db domains set mycontrib.mydomain.com domain Content Primary  Description mycontrib DocumentRoot /usr/share/mycontrib Nameservers internet RequireSSL enabled TemplatePath WebAppVirtualHost letsencryptSSLcert enabled

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

{

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



}

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