AlfClusterIns
From AlfrescoWiki
NOTE: THIS IS A WORK IN PROGRESS!! I'm in the process of creating it....
[edit] Purpose
Provide detailed instructions for installing Alfresco CE Cluster that services internal and external network users. The instructions will cover:
- Alfresco CE Cluster Installation Providing
- CIFS (internal)
- FTP (internal)
- Secure WebDAV (internal/external)
- Secure HTTPS (internal/external)
- NTLM User Authentication for Single Sign On (SSO) (internal)
- JAAS User Authentication (external)
- LDAP User Imports from Micrsoft AD
- Multilingual Menus
- Unique/Individual Site Branding with single Alfresco CE Cluster
- Nag Removal
- Keepalived for High Availability (HA) and Load Balancing (LB)
- Secure Apache HTTPD/mod_jk Tomcat installation and configuration
- Redhat ES5 Linux installation and configuration specific to Alfresco
- Oracle 10g DB example
[edit] Assumptions/Prerequisites
- A populated Microsoft Active Directory (AD) infrastructure
- A Oracle 10g DB Instance
- An Network File System (NFS) Server to house the Alfresco Repository
- Installer/Administrator has root/administrator privileges for all relevant systems
- A secure network with firewall policies
- Installer/Administrator is versed in installing RedHat operating systems and managing rpms
- Adequate NFS storage needs for your estimated Alfresco repository volume
- Installation will begin with a SINGLE non-HA/LB Alfresco CE instance. The cluster will be built up around it.
[edit] Create Oracle DB User
Before installing Alfresco you need a DB instance for Alfresco to connect to and populate. As the sql administrator create the ALFRESCO user identified by the password of your choosing. Change tablespace locations as neccessary. These are the minimum grants neccessary.
sql> CREATE USER "ALFRESCO" PROFILE "DEFAULT" IDENTIFIED BY "<!PASSWORD!>" DEFAULT TABLESPACE "ALFRESCO_DATA" TEMPORARY TABLESPACE "TEMP" QUOTA UNLIMITED ON "ALFRESCO_DATA" ACCOUNT UNLOCK; GRANT CONNECT TO "ALFRESCO"; GRANT CREATE ANY INDEX TO "ALFRESCO"; GRANT CREATE ANY PROCEDURE TO "ALFRESCO"; GRANT CREATE ANY SEQUENCE TO "ALFRESCO"; GRANT CREATE ANY SYNONYM TO "ALFRESCO"; GRANT CREATE ANY TABLE TO "ALFRESCO"; GRANT CREATE ANY TRIGGER TO "ALFRESCO"; GRANT CREATE ANY VIEW TO "ALFRESCO";
[edit] Install Alfresco Server
Create a SINGLE working Alfresco instance and then later we'll create 3 clones changing just 4 files.
[edit] Install RedHat System
- 1 RedHat ES Server (VMWARE OK).
- At least 2 NIC
- Enough disk for OS and Alfresco Installation
- Optional disk RAID
- /alf partition (Min. 400MB - Size as needed)
- /alt/tmp partition (AT LEAST 4GB)
You don't need a lot of disk or fast disks for that matter. It is CPU/IO intensive. The operating install will be dependent on your needs and environment. That being said I highly suggest the following partition layout with the at LEAST the /alf and /alf/tmp required:
/dev/sda1 2039 559 1377 29% / /dev/sda2 - SWAP /dev/sda3 6115 1371 4745 23% /usr /dev/sda5 510 109 401 22% /tmp /dev/sda6 1020 57 963 6% /var /dev/sda7 2039 75 1965 4% /var/log /dev/sda8 510 17 494 4% /home /dev/sda9 4077 373 3704 10% /alf /dev/sdb1 11900 32 11254 1% /alf/tmp
The /alf/tmp partition has EXT2 file system. It happens to be on a dedicated drive in our configuration. This tmp area is for the OpenOffice/Alfresco document conversions and the repository index rebuilds. In our experience 4GB was the MINIMUM for the temp storage area. As it is temporary we formatted with the EXT2 filesystem to eek some performance.
[edit] Configure Networking
In preparing for HA/LB with the LVS we will assign TWO network addresses. One will be the servers REAL address while the other address will be for the LVS service. LVS DIRECT requires NO-ARP for the virtual address. Unfortunately you can't have a single NIC for both the ARPing real address and an NON-ARPing alias address. The NIC is either all ARP or NO-ARP. Hence the need for a physical second NIC.
Configure the Real IP Address on ETH0. Season to taste.
DEVICE=eth0 BOOTPROTO=static BROADCAST=X.X.X.255 IPADDR=X.X.X.X NETMASK=255.255.255.0 NETWORK=X.X.X.0 ONBOOT=yes NOZEROCONF=yes USERCTL=no
Configure the Virtual IP Address on ETH1. Season to taste. Note: The most important setting is ARP=no !! This will be the 'shared' address for all the Alfresco clustered servers.
DEVICE=eth1 ARP=no KEEPALIVE=yes BOOTPROTO=static IPADDR=X.X.X.X NETMASK=255.255.255.0 NETWORK=X.X.X.0 TYPE=Ethernet NOZEROCONF=yes USERCTL=no ONBOOT=yes
[edit] Install Required RPMs with YUM, Current JAVA & OpenOffice
In our organization we used RedHat ES5 Update0 i386. We also removed all extra and unneccessary RPM packages.
- Alfresco depends on ImageMagick
- JAAS Authentication depends on Kerberos
Since there are so many dependencies with installing ImageMagick, install yum and let it do the work. (87+packages..)
[edit] Install YUM
rpm -i yum-3.0.1-5.el5.noarch.rpm python-elementtree-1.2.6-5.i386.rpm python-sqlite-1.1.7-1.2.1.i386.rpm rpm-python-4.4.2-37.el5.i386.rpm yum-metadata-parser-1.0-8.fc6.i386.rpm python-urlgrabber-3.1.0-2.noarch.rpm expat-1.95.8-8.2.1.i386.rpm m2crypto-0.16-6.el5.1.i386.rpm
[edit] Create Local Repository of RedHat ES5 RPMs
Install createrepo:
rpm -i createrepo-0.4.4-2.fc6.noarch.rpm
You'll have to expand the RPMs from the RedHat CDs/DVD and have them either on the NFS server and then reference/mount the collection to create a local repo.
createrepo /mnt/es5/U0/Expanded
Create a local.repo YUM config file
vi /etc/yum.repos.d/local.repo
Insert the local.repo config settings:
[localrepo] name=Fedora Core $releasever - My Local Repo baseurl=file:///mnt/es5/U0/Expanded enabled=1 gpgcheck=0 #gpgkey=file:///path/to/you/RPM-GPG-KEY
[edit] Install Kerberos
For JAAS Authentication install the Kerberos libraries. This is the minimum. If you want to test the config you'll need kinit which is in another krb rpm package.
rpm -i krb5-libs-1.5-17
[edit] Configure /etc/krb5.conf
Configure Kerberos for your environment. Here is an EXAMPLE config that we utilize.
- [!YOUR_AD_DOMAIN!] e.g. AD.COMPANY.COM or just COMPANY.COM It will depend on your organization. Also USE UPPER CASE for this setting.
- [!MICROSOFT_KRB_SERVER!] Your AD server address name. The server name is likely to be used in all subsequent settings for LDAP, NTLM and Kerberos.
- In [domain_realm] include any matching domains that AD would be authoritative.
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = [!YOUR_AD_DOMAIN!]
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
[realms]
[!YOUR_AD_DOMAIN!] = {
kdc = [!MICROSOFT_KRB_SERVER!]:88
admin_server = [!MICROSOFT_KRB_SERVER!]:749
default_domain = [!YOUR_AD_DOMAIN!]
}
[domain_realm]
.ad.company.com = [!YOUR_AD_DOMAIN!]
ad.company.com = [!YOUR_AD_DOMAIN!]
.company.com = [!YOUR_AD_DOMAIN!]
company.com = [!YOUR_AD_DOMAIN!]
[kdc]
profile = /var/kerberos/krb5kdc/kdc.conf
[appdefaults]
pam = {
debug = false
ticket_lifetime = 36000
renew_lifetime = 36000
forwardable = true
krb4_convert = false
}
[edit] Test Kerberos
If you need to test the Kerberos authentication configuration install the appropriate krb rpm package.
rpm -i krb5-workstation-1.5-17.i386.rpm
Then run kinit and supply just the username. If the config is correct the 'domain' will be appended. If the config is bad or mis-configured there will be errors reported.
kinit AD_USERNAME Password for AD_USERNAME@COMPANY.COM:
If the config is good and the password was correct a kerberos certificate should be listed. Run klist.
klist
You should see:
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: AD_USERNAME@COMPANY.COM
Valid starting Expires Service principal
08/31/07 17:40:25 09/01/07 03:40:29 krbtgt/COMPANY.COM@COMPANY.COM
renew until 09/01/07 17:40:25
Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached
[edit] Install ImageMagick
yum install ImageMagick
[edit] Alfresco/ImageMagick Quirk
Alfresco seems to make calls to imconvert. So, make a symbolic link.
ln -s /usr/bin/convert /usr/bin/imconvert
[edit] Install Java6.0u2
Get The JAVA 6.0u2 JDK from [Sun]. Agree to license and install the RPM.
rpm -i jdk-6u2-linux-i586.rpm
[edit] Remove/Re-install RedHat ALTERNATIVE Java
alternatives --remove java alternatives --install /usr/bin/java java /usr/java/default/jre/bin/java 1
[edit] Create java.sh Profile
vi /etc/profile.d/java.sh
export PATH=$PATH:/usr/java/default/jre/bin:/usr/java/default/bin export JAVA_HOME=/usr/java/default export JRE_HOME=/usr/java/default/jre export CLASSPATH=$CLASSPATH:/usr/java/default/lib/ojdbc14.jar
[edit] Source it..
. /etc/profile.d/java.sh
[edit] Install Oracle OJDBC.JAR
Alfresco with OracleDB depends on the Java JAR file ojdbc14.jar. You can get it from [Oracle] Copy/Move the jar file into /usr/java/default/lib/ then link it to /usr/java/default/jre/lib/
ln -s /usr/java/default/lib/ojdbc14.jar /usr/java/default/jre/lib/ojdbc14.jar
[edit] Install Xvfb for OpenOffice
OpenOffice will operate in a headless mode but needs a framebuffer to connect to. So install Xvfb. Xvfb will start BEFORE OpenOffice will start.
yum install Xvfb
[edit] Install LATEST OpenOffice
Get the current OpenOffice Linux suite [OOo_2.2.1_LinuxIntel_install_en-US.tar.gz]
You'll be running in OpenOffice in a HEADLESS configuration. But for the initial configuration/registration you'll need to have an available X session.
cd /usr/local/src tar xvfzp OOo_2.2.1_LinuxIntel_install_en-US.tar.gz.tar.gz cd OOF680_m18_native_packed-1_en-US.9161/RPMS rm openoffice.org-gnome-integration-2.2.1-9161.i586.rpm openoffice.org-kde-integration-2.2.1-9161.i586.rpm rpm -Uvih *.rpm export DISPLAY=<!SOMEHOST!>:0.0 /opt/openoffice.org2.2/program/soffice.bin
[edit] Set Soffice Temp Space
Go thru the registration and set the TEMPORARY file location to the big '/alf/tmp partition. In the OO GUI go to Tools:Options:Paths:Temporary Files and change /tmp to '/alf/tmp/soffice'. That's it. You can close it up.
[edit] Create SOFFICE INIT.D Script
This script will start Xvfb and wait for it prior to starting soffice in headless mode.
vi /etc/init.d/soffice
#!/bin/sh
#
# soffice
#
# chkconfig: 345 98 11
# description: Starts and stops the soffice non-interactive document transformation
# Source function library.
. /etc/rc.d/init.d/functions
XVFB=/usr/bin/Xvfb
SOFFICE=/opt/openoffice.org2.2/program/soffice.bin
SOFFICE_TMP=/alf/tmp/soffice
KILLER=/usr/bin/killall
case "$1" in
start)
#
# Start Soffice
#
echo -n "Starting Xvfb for SOFFICE: "
$XVFB :1 -screen 0 800x600x16 -fbdir /tmp > /dev/null 2>&1 &
sleep 3s
echo_success
echo
echo -n "Clearing SOFFICE ($SOFFICE_TMP): "
rm -rf $SOFFICE_TMP/*
echo_success
echo
echo -n "Starting SOFFICE: "
$SOFFICE -invisible -accept="socket,host=localhost,port=8100;urp;" -display :1 > /dev/null 2>&1 &
echo_success
echo
;;
startnow)
#
# Start Soffice
#
echo -n "Starting Xvfb for SOFFICE: "
$XVFB :1 -screen 0 800x600x16 -fbdir /tmp > /dev/null 2>&1 &
echo_success
echo
echo -n "Starting SOFFICE: "
$SOFFICE -invisible -accept="socket,host=localhost,port=8100;urp;" -display :1 > /dev/null 2>&1 &
echo_success
echo
;;
stop)
#
# Stop Soffice
#
echo -n "Stopping SOFFICE: "
$KILLER -q -s TERM soffice.bin
echo_success
echo
echo -n "Stopping Xvfb for SOFFICE: "
$KILLER -s TERM Xvfb
echo_success
echo
;;
*)
echo "Usage: $0 {start|startnow|stop}"
exit 1;;
esac
exit 0
Add the init script and disable it. Due to system dependencies if must be started in rc.local
chkconfig --add soffice chkconfig soffice off
[edit] Install Apache TOMCAT
Java must be installed and functional before installing Apache Tomcat!
We prefer Apache Tomcat from [source] rather than RPMs. If you use RPMs then you'll need to accomodate for path differences. We used apache-tomcat-6.0.13
cd /usr/local tar xvfzp <!PATH!>/apache-tomcat-6.0.13.tar.gz mv apache-tomcat-6.0.13 tomcat
Add/Create the TOMCAT user and group. Season to taste.
echo "tomcat:x:52:52:Tomcat:/usr/local/tomcat:/sbin/nologin" >> /etc/passwd echo "tomcat:x:52:" >> /etc/group
Unpack the service scripts that help manage tomcat more easily
cd /usr/local/tomcat/bin tar xfvzp jsvc.tar.gz cd jsvc-src sh ./configure make
Change ownership and put logs in /var/log.
chown -R tomcat.tomcat /usr/local/tomcat rm -rf /usr/local/tomcat/logs mkdir /var/log/tomcat chown -R tomcat.tomcat /var/log/tomcat ln -s /var/log/tomcat /usr/local/tomcat/logs
[edit] Create New Tomcat TEMP
If it doesn't exist create it.
mkdir /alf/tmp/tomcat
Change ownership on /alf/tmp to tomcat user.
chown -R tomcat.tomcat /alf/tmp
[edit] Edit /usr/local/tomcat/conf/server.xml
- [!REAL_SERVER_IP_ADDRESS!] The IP address assigned to eth0.
- [!YOUR_WEB_FQDN!] Set to the Fully Qualified Domain Name for accessing the Alfresco web server. e.g. www.alfresco.company.com
- Uncomment the 8080 HTTP Connector. This will enable you to connect via the browser for this single server setup. After the setup is complete and the server has been cloned and placed into the cluster you should re-comment out this section for security.
- The <Alias> directive will be used later for custom site branding.
Replace the contents with this minimal set:
<Server debug="0" port="8005" shutdown="SHUTDOWN">
<Service name="Alfresco-Service">
<!--
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<Connector protocol="AJP/1.3" address="[!REAL_SERVER_IP_ADDRESS!]"
port="8009" minProcessors="15" maxProcessors="200"
enableLookups="false" redirectPort="8443" emptySessionPath="true"
acceptCount="10" debug="0" connectionTimeout="60000"
useURIValidationHack="false" URIEncoding="UTF-8"/>
<Engine jvmRoute="fresco1" debug="0" name="Alfresco-Engine">
<Realm className="org.apache.catalina.realm.MemoryRealm" />
<!-- ============================================================
Alfresco
============================================================ -->
<Host name="[!YOUR_FQDN_WEB!]" appBase="/alf/alfy"
debug="0" autoDeploy="false" unpackWARs="false">
<!-- ALIAS for additonal site names for custom branding e.g., -->
<!-- <Alias>alfresco.company1.com</Alias> -->
<!-- <Alias>alfresco.company2.com</Alias> -->
<!-- <Alias>alfresco.company3.com</Alias> -->
<Context docBase="" path=""/>
<Valve className="org.apache.catalina.valves.FastCommonAccessLogValve" directory="logs"
prefix="alfresco_access." suffix=".log" pattern="common" resolveHosts="false"/>
</Host>
</Engine>
</Service>
</Server>
[edit] Create TOMCAT INIT.D Script
NOTE: java.io.tmpdir is changed to /alf/tmp/tomcat
vi /etc/init.d/tomcat
#!/bin/sh
#
# tomcat Utilizing the jsvc start and stop the servlet engine.
#
# chkconfig: 345 99 10
# description: Starts and stops the tomcat servlet engine.
# Source function library.
. /etc/rc.d/init.d/functions
##############################################################################
#
# Copyright 2004 The Apache Software Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################
#
# Small shell script to show how to start/stop Tomcat using jsvc
# If you want to have Tomcat running on port 80 please modify the server.xml
# file:
#
# <!-- Define a non-SSL HTTP/1.1 Connector on port 80 -->
# <Connector className="org.apache.catalina.connector.http.HttpConnector"
# port="80" minProcessors="5" maxProcessors="75"
# enableLookups="true" redirectPort="8443"
# acceptCount="10" debug="0" connectionTimeout="60000"/>
#
# That is for Tomcat-5.0.x (Apache Tomcat/5.0)
#
# Adapt the following lines to your configuration
JAVA_HOME=/usr/java/default/jre
CATALINA_HOME=/usr/local/tomcat
DAEMON_HOME=/usr/local/tomcat/bin/jsvc-src
TOMCAT_USER=tomcat
TOMCAT_GROUP=tomcat
TOMCAT_PID=/var/run/jsvc.pid
TMP_DIR=/alf/tmp/tomcat
CATALINA_OPTS=
CLASSPATH=$JAVA_HOME/lib/ojdbc14.jar:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/bin/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar
CATALINA_WORK_DIR=$CATALINA_HOME/work
# To get a verbose JVM
#-verbose \
# To get a debug of jsvc.
#-debug \
WAIT_MAX=2
case "$1" in
start)
#
# Start Tomcat
#
# Wait for SOFFICE 2 times...
WAIT=1
while [ $WAIT -le $WAIT_MAX ];
do
echo -n "Waiting for SOFFICE ($WAIT/$WAIT_MAX 1min):"
SOFFICE=`netstat -an | grep 8100`
if [ -n "$SOFFICE" ]; then
echo_success
TOMCAT_CONTINUE=TRUE
let WAIT=$WAIT_MAX+1
else
echo_failure
TOMCAT_CONTINUE=FALSE
let WAIT+=1
sleep 1m
fi
echo
done
echo -n "Starting Tomcat: "
if [ $TOMCAT_CONTINUE = 'FALSE' ]; then
echo_failure
echo
exit 1
fi
# Tuned for low pause times and high throughput i-cms
# For monitoring...
#-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:-TraceClassUnloading \
#-Xms2304m -Xmx2304m -Xmn768m -Xss2048k -XX:+AggressiveOpts\
#-Xmx1024m -Xms1024m -XX:+UseLargePages -XX:LargePageSizeInBytes=1m \
#-Xmx1536m \
$DAEMON_HOME/jsvc \
-user $TOMCAT_USER \
-home $JAVA_HOME \
-jvm server \
-Xmx1536m \
-Dcatalina.home=$CATALINA_HOME \
-Djava.io.tmpdir=$TMP_DIR \
-outfile $CATALINA_HOME/logs/catalina.out \
-errfile '&1' \
$CATALINA_OPTS \
-cp $CLASSPATH \
org.apache.catalina.startup.Bootstrap
sleep 2s
if [ -f $TOMCAT_PID ]; then
echo_success
else
echo_failure
fi
echo
;;
stop)
#
# Stop Tomcat
#
echo -n "Stopping Tomcat: "
PID=`cat $TOMCAT_PID`
kill $PID 2>/dev/null 1>/dev/null
if [ `ps -p ${PID} > /dev/null 2>&1` ]; then
echo_failure
else
echo_success
rm -f $TOMCAT_PID > /dev/null 2>&1
fi
echo
;;
flush)
#
# Stop Tomcat
#
echo -n "Stopping Tomcat: "
PID=`cat $TOMCAT_PID`
kill $PID 2>/dev/null 1>/dev/null
if [ `ps -p ${PID} > /dev/null 2>&1` ]; then
echo_failure
else
echo_success
rm -f $TOMCAT_PID > /dev/null 2>&1
fi
echo
echo -n "Flushing Tomcat CACHE ($CATALINA_WORK_DIR) : "
rm -rf $CATALINA_WORK_DIR
if [ -e $CATALINA_WORK_DIR ]; then
echo_failure
echo
exit 1;
fi
mkdir $CATALINA_WORK_DIR
chown $TOMCAT_USER.$TOMCAT_GROUP $CATALINA_WORK_DIR
if [ ! -e $CATALINA_WORK_DIR ]; then
echo_failure
echo
exit 1;
fi
echo_success
echo
;;
*)
echo "Usage: $0 {start|stop|flush}"
exit 1;;
esac
exit 0
Add the init script and disable it. Due to system dependencies if must be started in rc.local
chkconfig --add tomcat chkconfig tomcat off
[edit] Create Services
Because of an soffice XVfb dependency wait until all other rc levels are run. Insert the following into /etc/init.d/rc.local
service soffice start service tomcat start
[edit] Create IPTables Local NAT for Alfresco CIFS, FTP
Running Alfresco/Tomcat as the tomcat user prevents binding to ports lower than 1024. In anticipation of this local NAT rules with iptables allows connections to the standard CIFS and FTP ports while running Alfresco/Tomcat with a non-root user. I'm assuming you have iptables installed. If not you know the drill. CAUTION: This clears an existing iptables setting. If you already have an iptables policy SAVE IT and add these NAT rules to it and reload.
Clear iptables
iptables -F iptables -X
The NAT rules for high to low routing:
iptables -t nat -A PREROUTING -p tcp --dport 445 -i eth0 -j REDIRECT --to-port 2445 iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 445 -j REDIRECT --to-port 2445 iptables -t nat -A PREROUTING -p tcp --dport 139 -i eth0 -j REDIRECT --to-port 2139 iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 139 -j REDIRECT --to-port 2139 iptables -t nat -A PREROUTING -p udp --dport 137 -i eth0 -j REDIRECT --to-port 2137 iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 137 -j REDIRECT --to-port 2137 iptables -t nat -A PREROUTING -p udp --dport 138 -i eth0 -j REDIRECT --to-port 2138 iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 138 -j REDIRECT --to-port 2138 iptables -t nat -A PREROUTING -p udp --dport 21 -i eth0 -j REDIRECT --to-port 2021 iptables -t nat -A OUTPUT -p udp -d 127.0.0.1 --dport 21 -j REDIRECT --to-port 2021 iptables -t nat -A PREROUTING -p tcp --dport 21 -i eth0 -j REDIRECT --to-port 2021 iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 21 -j REDIRECT --to-port 2021
To save state between restarts:
service iptables save
[edit] Install Alfresco CE 2.1
We will not be using the Alfresco user database for authentication. Instead we will be importing users via LDAP from the Microsoft AD and relying on NTLM passthru and JAAS/Kerberos authentication.
Get the community source WAR file [alfresco-community-war-2.1.0.tar.gz]
Create the working directory /alf/alfy and unzip the alfresco.war file.
cd /alf tar xvfzp alfresco-community-war-2.1.0R1.tar.gz mkdir alfy cd alfy unzip ../alfresco.war chown -R tomcat.tomcat /alf/*
Create the lucene indexes directory. This will NOT be shared in the cluster. The lucene indexes must exist locally for each cluster member server.
mkdir /alf/alf_data
Create the repository directory. This will later be moved to the NFS server and automounted amongst the Alfresco cluster member servers.
mkdir /alf/alf_data_cluster
[edit] Add Language Extensions
To enable the multi-lingual menus in Alfresco web copy the translation extensions. This is optional but a very nice one.
cp -ax /alf/extensions/messages/* /alf/alfy/WEB-INF/classes/alfresco/messages
[edit] Alfresco CONFIG Changes
These are important! Most examples are reports from running diff -u. Custom configurations are created in extensions sub-directory.
[edit] /alf/alfy/WEB-INF/classes/log4j.properties
Redirect logging to a better location.
log4j.appender.File.File=/var/log/tomcat/alfresco.log
[edit] /alf/alfy/WEB-INF/classes/alfresco/domain/hibernate-cfg.properties
Accomodate for using Oracle DB.
@@ -1,7 +1,7 @@ # # Hibernate configuration # -hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.Oracle9Dialect hibernate.jdbc.use_streams_for_binary=true hibernate.show_sql=false
[edit] /alf/alfy/WEB-INF/classes/alfresco/repository.properties
DON'T change user.name.caseSensitive=false.
Reflect the repository directory changes.
@@ -1,11 +1,10 @@
# Directory configuration
-dir.root=./alf_data
+dir.root=/alf/alf_data
-dir.contentstore=${dir.root}/contentstore
-dir.contentstore.deleted=${dir.root}/contentstore.deleted
-
-dir.auditcontentstore=${dir.root}/audit.contentstore
+dir.contentstore=/alf/alf_data_cluster
+dir.contentstore.deleted=${dir.contentstore}/contentstore.deleted
+dir.auditcontentstore=${dir.contentstore}/audit.contentstore
# The location for lucene index files
dir.indexes=${dir.root}/lucene-indexes
Change the Index Recovery to AUTO. Likely need set to FULL on first startup.
@@ -14,7 +13,8 @@
dir.indexes.lock=${dir.indexes}/locks
# The index recovery mode (NONE, VALIDATE, AUTO, FULL)
-index.recovery.mode=VALIDATE
+index.recovery.mode=AUTO
+#index.recovery.mode=FULL
# Change the failure behaviour of the configuration checker
system.bootstrap.config_check.strict=true
Reflect the Oracle DB settings and email host settings.
@@ -70,16 +70,17 @@
# Database configuration
db.schema.update=true
-db.driver=org.gjt.mm.mysql.Driver
+db.driver=oracle.jdbc.OracleDriver
db.name=alfresco
-db.url=jdbc:mysql:///${db.name}
-db.username=alfresco
+db.url=jdbc:oracle:thin:@<!ORACLE_DB_SERVER!>:1521:<!YOUR_DB_INSTANCE!>
+db.username=ALFRESCO
db.password=<!ORACLE_ALFRESCO_USER_PASSWORD!>
db.pool.initial=10
db.pool.max=20
# Email configuration
-mail.host=
+mail.host=<!YOUR_MAIL_HOST!>
mail.port=25
mail.username=anonymous
mail.password=
Reflect a valid default FROM email address.
@@ -87,7 +88,7 @@ mail.encoding=UTF-8 # Set this value to 7bit or similar for Asian encoding of email headers as required mail.header= -mail.from.default=alfresco@alfresco.org +mail.from.default=<!YOUR_ADMIN_EMAIL_ADDRESS!> # System Configuration system.store=system://system
[edit] /alf/alfy/WEB-INF/classes/alfresco/scheduled-jobs-context.xml
Due to a quirk in Alfresco 2.1 CE and LDAP imports with the Quartz schedueler change the autoStartup to true.
@@ -18,7 +18,7 @@
</property>
<!-- Do not auto start the scheduler - this is done at the end of the bootstrap process -->
<property name="autoStartup">
- <value>false</value>
+ <value>true</value>
</property>
</bean>
[edit] /alf/alfy/WEB-INF/classes/alfresco/authentication-services-context.xml
Disable GuestLogins
@@ -155,7 +155,7 @@
<ref bean="authenticationManager" />
</property>
<property name="allowGuestLogin">
- <value>true</value>
+ <value>false</value>
</property>
</bean>
Disallow creating missing people. We get them form the LDAP import. The default settings for handling duplicate usernames was sufficient for our needs. Unless you know what you are doing with them I'd leave the settings for proccessing duplicates alone.
@@ -216,7 +216,8 @@
<!-- ${server.transaction.allow-writes} -->
<!-- false -->
<property name="createMissingPeople">
- <value>${server.transaction.allow-writes}</value>
+ <!--<value>${server.transaction.allow-writes}</value>-->
+ <value>false</value>
</property>
<property name="userNamesAreCaseSensitive">
<value>${user.name.caseSensitive}</value>
Added a Default Home Folder to match Personal Home Folders under User Homes. Change the location of Personal Home Folders to reside in /Company Home/User Homes.
@@ -290,12 +291,18 @@
</property>
</bean>
+ <bean name="defaultHomeFolderProvider" class="org.alfresco.repo.security.person.UIDBasedHomeFolderProvider">
+ <property name="homeFolderManager">
+ <ref bean="homeFolderManager" />
+ </property>
+ </bean>
+
<bean name="personalHomeFolderProvider" class="org.alfresco.repo.security.person.UIDBasedHomeFolderProvider">
<property name="serviceRegistry">
<ref bean="ServiceRegistry" />
</property>
<property name="path">
- <value>/${spaces.company_home.childname}</value>
+ <value>/${spaces.company_home.childname}/${spaces.user_homes.childname}</value>
</property>
<property name="storeUrl">
<value>${spaces.store}</value>
<pre>
<bean name="personalHomeFolderProvider" class="org.alfresco.repo.security.person.UIDBasedHomeFolderProvider">
<property name="serviceRegistry">
<ref bean="ServiceRegistry" />
</property>
<property name="path">
- <value>/${spaces.company_home.childname}</value>
+ <value>/${spaces.company_home.childname}/${spaces.user_homes.childname}</value>
</property>
<property name="storeUrl">
<value>${spaces.store}</value>
[edit] /alf/alfy/WEB-INF/classes/alfresco/authority-services-context.xml
Add additional users from AD for administrative priveleges.
<property name="adminUsers">
<set>
<value>admin</value>
<value>administrator</value>
<value>!ADUSERNAME!</value>
</set>
</property>
[edit] /alf/alfy/WEB-INF/classes/alfresco/extension/ldap-authentication-context.xml
This critical extension enables the importation of users and groups from the Microsoft Active Directory via LDAP. It may take some patience to adjust this file to your needs. Once settled though make sure set clearAllChildren=false for user imports. It will minimize interuptions when users login during import jobs. User accounts if non-existant will create usernamed home directories in under the 'Company Home/User Homes'. If you want them created somewhere else you'll need to modify the cm:homeFolderProvider.
- [!SERVER_NAME!] Can be any unique network computer name. ALFY1, FRESCO1, MONET1, etc.
- [!YOUR_DOMAIN_NAME!] is the Microsoft AD Domain Name that the Alfresco CIFS server will be registered in.
- [!MICROSOFT_LDAP_SERVER_ADDRESS!] The fqdn of you Microsoft AD Server that will authenticate users.
- [!LDAP_READ_USER!] A user with READ access across the entire tree. Of the format USERNAME@AD_DOMAIN_NAME
- [!LDAP_READ_USER_PASSWORD!]
- [!COMPANY!] [!TLD!] is YOUR_DOMAIN_NAME in parts i.e., company and com respectively.
The personQuery can trip you up. But this works well for Microsoft AD. It only imports users that have a givenName, surname and email values in their accounts. So, if you aren't seeing users that you expect a user may be lacking one or more of these values.
<property name="personQuery">
<value><![CDATA[(&(objectClass=user)(givenName=*)(sn=*)(mail=*))]]></value>
</property>
The groupQuery is also tricky. But this works well for our purposes. Rather than clutter the Alfresco group management with groups that are not of any relevance we only import alfresco groups. Modify to meet your needs.
<property name="groupQuery">
<value><![CDATA[(&(objectclass=group)(cn=*Alfresco*))]]></value>
</property>
Make sure the searchBase is correct for your environment.
<property name="searchBase">
<value>dc=[!COMPANY!],dc=[!TLD!]</value>
</property>
Per the notes in the file and from our experience this setting is accurate.
<property name="userIdAttributeName">
<value>sAMAccountName</value>
</property>
vi /alf/alfy/WEB-INF/classes/alfresco/extension/ldap-authentication-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- DAO that rejects changes - LDAP is read only at the moment. It does allow users to be deleted with out warnings from the UI. -->
<bean name="authenticationDao" class="org.alfresco.repo.security.authentication.DefaultMutableAuthenticationDao" >
<property name="allowDeleteUser">
<value>true</value>
</property>
</bean>
<!--
This bean is used to support general LDAP authentication. It is also used to provide read only access to users and groups
to pull them out of the LDAP reopsitory
-->
<bean id="ldapInitialDirContextFactory" class="org.alfresco.repo.security.authentication.ldap.LDAPInitialDirContextFactoryImpl">
<property name="initialDirContextEnvironment">
<map>
<!-- The LDAP provider -->
<entry key="java.naming.factory.initial">
<value>com.sun.jndi.ldap.LdapCtxFactory</value>
</entry>
<!-- The url to the LDAP server -->
<!-- Note you can use space separated urls - they will be tried in turn until one works -->
<!-- This could be used to authenticate against one or more ldap servers (you will not know which one ....) -->
<entry key="java.naming.provider.url">
<value>ldap://[!MICROSOFT_LDAP_SERVER_ADDRESS!]:389</value>
</entry>
<!-- The authentication mechanism to use -->
<!-- Some sasl authentication mechanisms may require a realm to be set -->
<!-- java.naming.security.sasl.realm -->
<!-- The available options will depend on your LDAP provider -->
<entry key="java.naming.security.authentication">
<value>simple</value>
</entry>
<!-- The id of a user who can read group and user information -->
<!-- This does not go through the pattern substitution defined above and is used "as is" -->
<entry key="java.naming.security.principal">
<value>[!LDAP_READ_USER!]</value>
</entry>
<!-- The password for the user defined above -->
<entry key="java.naming.security.credentials">
<value>[!LDAP_READ_USER_PASSWORD!]</value>
</entry>
</map>
</property>
</bean>
<!-- Ldap Syncronisation support -->
<!--
There can be more than one stack of beans that import users or groups. For example, it may be easier
to have a version of ldapPeopleExportSource, and associated beans, for each sub-tree of your ldap directory
from which you want to import users. You could then limit users to be imported from two or more sub tress and ignore
users found else where. The same applies to the import of groups.
The defaults shown below are for OpenLDAP.
-->
<!-- Extract user information from LDAP and transform this to XML -->
<bean id="ldapPeopleExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPPersonExportSource">
<!--
The query to select objects that represent the users to import.
For Open LDAP, using a basic schema, the following is probably what you want:
(objectclass=inetOrgPerson)
For Active Directory:
(objectClass=user)
-->
<property name="personQuery">
<value><![CDATA[(&(objectClass=user)(givenName=*)(sn=*)(mail=*))]]></value>
</property>
<!--
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
-->
<property name="searchBase">
<value>dc=[!COMPANY!],dc=[!TLD!]</value>
</property>
<!--
The unique identifier for the user.
THIS MUST MATCH WHAT THE USER TYPES IN AT THE LOGIN PROMPT
For simple LDAP authentication this is likely to be "cn" or, less friendly, "distinguishedName"
In OpenLDAP, using other authentication mechanisms "uid", but this depends on how you map
from the id in the LDAP authentication request to search for the inetOrgPerson against which
to authenticate.
In Active Directory this is most likely to be "sAMAccountName"
This property is mandatory and must appear on all users found by the query defined above.
-->
<property name="userIdAttributeName">
<value>sAMAccountName</value>
</property>
<!-- Services -->
<property name="LDAPInitialDirContextFactory">
<ref bean="ldapInitialDirContextFactory"/>
</property>
<property name="personService">
<ref bean="personService"></ref>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<!--
This property defines a mapping between attributes held on LDAP user objects and
the properties of user objects held in the repository. The key is the QName of an attribute in
the repository, the value is the attribute name from the user/inetOrgPerson/.. object in the
LDAP repository.
-->
<property name="attributeMapping">
<map>
<entry key="cm:userName">
<!-- Must match the same attribute as userIdAttributeName -->
<value>sAMAccountName</value>
</entry>
<entry key="cm:firstName">
<!-- OpenLDAP: "givenName" -->
<!-- Active Directory: "givenName" -->
<value>givenName</value>
</entry>
<entry key="cm:lastName">
<!-- OpenLDAP: "sn" -->
<!-- Active Directory: "sn" -->
<value>sn</value>
</entry>
<entry key="cm:email">
<!-- OpenLDAP: "mail" -->
<!-- Active Directory: "???" -->
<value>mail</value>
</entry>
<entry key="cm:organizationId">
<!-- OpenLDAP: "o" -->
<!-- Active Directory: "???" -->
<value>o</value>
</entry>
<!-- Always use the default -->
<entry key="cm:homeFolderProvider">
<null/>
</entry>
</map>
</property>
<!-- Set a default home folder provider -->
<!-- Defaults only apply for values above -->
<property name="attributeDefaults">
<map>
<entry key="cm:homeFolderProvider">
<value>personalHomeFolderProvider</value>
</entry>
</map>
</property>
</bean>
<!-- Extract group information from LDAP and transform this to XML -->
<bean id="ldapGroupExportSource" class="org.alfresco.repo.security.authentication.ldap.LDAPGroupExportSource">
<!--
The query to select objects that represent the groups to import.
For Open LDAP, using a basic schema, the following is probably what you want:
(objectclass=groupOfNames)
For Active Directory:
(objectclass=group)
-->
<property name="groupQuery">
<value><![CDATA[(&(objectclass=group)(cn=*Alfresco*))]]></value>
</property>
<!--
The seach base restricts the LDAP query to a sub section of tree on the LDAP server.
-->
<property name="searchBase">
<value>dc=ad,dc=menasha,dc=com</value>
</property>
<!--
The unique identifier for the user. This must match the userIdAttributeName on the ldapPeopleExportSource bean above.
-->
<property name="userIdAttributeName">
<value>sAMAccountName</value>
</property>
<!--
An attribute that is a unique identifier for each group found.
This is also the name of the group with the current group implementation.
This is mandatory for any groups found.
OpenLDAP: "cn" as it is mandatory on groupOfNames
Active Directory: "cn"
-->
<property name="groupIdAttributeName">
<value>cn</value>
</property>
<!--
The objectClass attribute for group members.
For each member of a group, the distinguished name is given.
The object is looked up by its DN. If the object is of this class it is treated as a group.
-->
<property name="groupType">
<value>group</value>
</property>
<!--
The objectClass attribute for person members.
For each member of a group, the distinguished name is given.
The object is looked up by its DN. If the object is of this class it is treated as a person.
-->
<property name="personType">
<value>person</value>
</property>
<property name="LDAPInitialDirContextFactory">
<ref bean="ldapInitialDirContextFactory"/>
</property>
<property name="namespaceService">
<ref bean="namespaceService"/>
</property>
<!--
The repeating attribute on group objects (found by query or as sub groups)
used to define membership of the group. This is assumed to hold distinguished names of
other groups or users/people; the above types are used to determine this.
OpenLDAP: "member" as it is mandatory on groupOfNames
Active Directory: "member"
-->
<property name="memberAttribute">
<value>member</value>
</property>
<property name="authorityDAO">
<ref bean="authorityDAO"/>
</property>
</bean>
<!-- Job definitions to import LDAP people and groups -->
<!-- The triggers register themselves with the scheduler -->
<!-- You may comment in the default scheduler to enable these triggers -->
<!-- If a cron base trigger is what you want seee scheduled-jobs-context.xml for examples. -->
<!-- Trigger to load poeple -->
<!-- Note you can have more than one initial (context, trigger, import job and export source) set -->
<!-- This would allow you to load people from more than one ldap store -->
<bean id="ldapPeopleTrigger" class="org.alfresco.util.TriggerBean">
<property name="jobDetail">
<bean id="ldapPeopleJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>org.alfresco.repo.importer.ImporterJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="bean">
<ref bean="ldapPeopleImport"/>
</entry>
</map>
</property>
</bean>
</property>
<!-- Start after 8 minutes of starting the repository -->
<property name="startDelay">
<value>480000</value>
</property>
<!-- Repeat every 1.25 hour -->
<property name="repeatInterval">
<value>4500000</value>
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
</bean>
<bean id="ldapGroupTrigger" class="org.alfresco.util.TriggerBean">
<property name="jobDetail">
<bean id="ldapGroupJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>org.alfresco.repo.importer.ImporterJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="bean">
<ref bean="ldapGroupImport"/>
</entry>
</map>
</property>
</bean>
</property>
<!-- Start after 3 minutes of starting the repository -->
<property name="startDelay">
<value>180000</value>
</property>
<!-- Run every 4 hours -->
<property name="repeatInterval">
<value>14400000</value>
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
</bean>
<!-- The bean that imports xml describing people -->
<bean id="ldapPeopleImport" class="org.alfresco.repo.importer.ExportSourceImporter">
<property name="importerService">
<ref bean="importerComponentWithBehaviour"/>
</property>
<property name="transactionService">
<ref bean="transactionComponent"/>
</property>
<property name="authenticationComponent">
<ref bean="authenticationComponent"/>
</property>
<property name="exportSource">
<ref bean="ldapPeopleExportSource"/>
</property>
<!-- The store that contains people - this should not be changed -->
<property name="storeRef">
<value>${spaces.store}</value>
</property>
<!-- The location of people nodes within the store defined above - this should not be changed -->
<property name="path">
<value>/${system.system_container.childname}/${system.people_container.childname}</value>
</property>
<!-- If true, clear all existing people before import, if false update/add people from the xml -->
<property name="clearAllChildren">
<value>false</value>
</property>
<property name="nodeService">
<ref bean="nodeService"/>
</property>
<property name="searchService">
<ref bean="searchService"/>
</property>
<property name="namespacePrefixResolver">
<ref bean="namespaceService"/>
</property>
<property name="caches">
<set>
<ref bean="permissionsAccessCache"/>
</set>
</property>
</bean>
<!-- The bean that imports xml descibing groups -->
<bean id="ldapGroupImport" class="org.alfresco.repo.importer.ExportSourceImporter">
<property name="importerService">
<ref bean="importerComponentWithBehaviour"/>
</property>
</bean>
<!-- The bean that imports xml descibing groups -->
<bean id="ldapGroupImport" class="org.alfresco.repo.importer.ExportSourceImporter">
<property name="importerService">
<ref bean="importerComponentWithBehaviour"/>
</property>
<property name="transactionService">
<ref bean="transactionComponent"/>
</property>
<property name="authenticationComponent">
<ref bean="authenticationComponent"/>
</property>
<property name="exportSource">
<ref bean="ldapGroupExportSource"/>
</property>
<!-- The store that contains group information - this should not be changed -->
<property name="storeRef">
<value>${alfresco_user_store.store}</value>
</property>
<!-- The location of group information in the store above - this should not be changed -->
<property name="path">
<value>/${alfresco_user_store.system_container.childname}/${alfresco_user_store.authorities_container.childname}</value>
</property>
<!-- If true, clear all existing groups before import, if false update/add groups from the xml -->
<property name="clearAllChildren">
<value>true</value>
</property>
<property name="nodeService">
<ref bean="nodeService"/>
</property>
<property name="searchService">
<ref bean="searchService"/>
</property>
<property name="namespacePrefixResolver">
<ref bean="namespaceService"/>
</property>
<!-- caches to clear on import of groups -->
<property name="caches">
<set>
<ref bean="userToAuthorityCache"/>
<ref bean="permissionsAccessCache"/>
</set>
</property>
<!-- userToAuthorityCache -->
</bean>
</beans>
[edit] /alf/alfy/WEB-INF/classes/alfresco/extension/jaas-authentication-context.xml
This important extension enables the JAAS user authentication mechanism for the Alfresco WEB interface.
vi /alf/alfy/WEB-INF/classes/alfresco/extension/jaas-authentication-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- The authentication component. -->
<!-- Jass authentication - most of the config goes somewhere else -->
<bean id="authenticationComponent"
class="org.alfresco.repo.security.authentication.jaas.JAASAuthenticationComponent">
<property name="realm">
<value>AD.MENASHA.COM</value>
</property>
<property name="jaasConfigEntryName">
<value>Alfresco</value>
</property>
</bean>
<bean id="alfDaoImpl" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<value>
org.alfresco.repo.security.authentication.MutableAuthenticationDao
</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<bean class="org.alfresco.repo.security.authentication.ntlm.NullMutableAuthenticationDao" />
</property>
<property name="transactionAttributes">
<props>
<prop key="*">${server.transaction.mode.default}</prop>
</props>
</property>
</bean>
</beans>
[edit] /alf/alfy/WEB-INF/classes/alfresco/extension/file-servers-custom.xml
This extension will enable CIFS, FTP and NTLM Passthru to the Microsoft AD server. The Alfresco WEB interface is authenticating with JAAS.
- [!SERVER_NAME!] Can be any unique network computer name. ALFY1, FRESCO1, MONET1, etc.
- [!YOUR_DOMAIN_NAME!] is the Microsoft AD Domain Name that the Alfresco CIFS server will be registered in.
- [!SERVER_REAL_IP_ADDRESS!] For now this is the address you assigned on interface eth0. Later when we enable the cluster this will change to the non-arping virtual address on eth1.
- [!WINS_SERVER_IP_ADDRESS!] Is your WINS server IP address.
- [!YOUR_WEB_FQDN!] Set to the Fully Qualified Domain Name for accessing the Alfresco web server. e.g. www.alfresco.company.com
- [!MICROSOFT_AD_SERVER_ADDRESS!] The fqdn/ip of you Microsoft AD Server that will authenticate users.
vi /alf/alfy/WEB-INF/classes/alfresco/extension/file-servers-custom.xml
<alfresco-config area="file-servers">
<config evaluator="string-compare" condition="CIFS Server" replace="true">
<serverEnable enabled="true"/>
<host name="[!SERVER_NAME!]" domain="[!YOUR_DOMAIN_NAME!]"/>
<comment>CIFS</comment>
<sessionDebug flags="Negotiate,NetBIOS,State,Tree,Search,Info,File,FileIO,Tran,Echo,Errors,IPC,Lock,Pkttype,Dcerpc,Statecache,Notify,Streams,Socket"/>
<!-- Set to the broadcast mask for the subnet -->
<bindto>[!SERVER_REAL_IP_ADDRESS!]</bindto>
<broadcast>X.X.X.255</broadcast>
<!-- Use Java socket based NetBIOS over TCP/IP and native SMB on linux -->
<tcpipSMB port="2445" platforms="linux"/>
<netBIOSSMB bindto="[!SERVER_REAL_IP_ADDRESS!]" sessionPort="2139" namePort="2137" datagramPort="2138" platforms="linux"/>
<hostAnnounce interval="5"/>
<!-- Use Win32 NetBIOS interface on Windows
<Win32NetBIOS/>
<Win32Announce interval="5"/>
-->
<WINS>
<primary>[!WINS_SERVER_IP_ADDRESS!]</primary>
</WINS>
</config>
<config evaluator="string-compare" condition="FTP Server" replace="true">
<serverEnable enabled="true"/>
<debug flags="File,Search,Error,Directory,Info,DataPort"/>
<port>2021</port>
<bindto>[!SERVER_REAL_IP_ADDRESS!]</bindto>
<rootDirectory>/Alfresco</rootDirectory>
</config>
<config evaluator="string-compare" condition="NFS Server" replace="true">
<serverEnable enabled="false"/>
<enablePortMapper/>
<rpcAuthenticator>
<userMappings>
<user name="admin" uid="0" gid="0"/>
<user name="auser" uid="501" gid="501"/>
</userMappings>
</rpcAuthenticator>
</config>
<config evaluator="string-compare" condition="Filesystems" replace="true">
<filesystems>
<filesystem name="Alfresco">
<store>workspace://SpacesStore</store>
<rootPath>/app:company_home</rootPath>
<!-- Add a URL file to each folder that links back to the web client -->
<urlFile>
<filename>__Alfresco.url</filename>
<webpath>https://[!YOUR_WEB_FQDN!]/</webpath>
</urlFile>
<!-- Mark locked files as offline -->
<offlineFiles/>
<desktopActions>
<global>
<path>alfresco/desktop/Alfresco.exe</path>
<webpath>https://[!YOUR_WEB_FQDN!]/</webpath>
</global>
<action>
<class>org.alfresco.filesys.smb.server.repo.desk.CheckInOutDesktopAction</class>
<name>CheckInOut</name>
<filename>__CheckInOut.exe</filename>
</action>
<action>
<class>org.alfresco.filesys.smb.server.repo.desk.JavaScriptDesktopAction</class>
<name>JavaScriptURL</name>
<filename>__ShowDetails.exe</filename>
<script>alfresco/desktop/showDetails.js</script>
<attributes>anyFiles</attributes>
<preprocess>copyToTarget</preprocess>
</action>
</desktopActions>
</filesystem>
<!-- AVM virtualization view of all stores/versions for WCM -->
<avmfilesystem name="AVM">
<virtualView/>
</avmfilesystem>
</filesystems>
</config>
<config evaluator="string-compare" condition="Filesystem Security" replace="true">
<authenticator type="passthru">
<Server>[!MICROSOFT_AD_SERVER_ADDRESS!]</Server>
<Domain>[!YOUR_DOMAIN_NAME!]</Domain>
</authenticator>
</config>
</alfresco-config>
[edit] /alf/alfy/WEB-INF/classes/alfresco/extension/index-tracking-context.xml
This extension will keep keep the search index refreshed as documents are added/removed from the repository.
vi /alf/alfy/WEB-INF/classes/alfresco/extension/index-tracking-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Schedule index tracking every 10s -->
<bean id="indexTrackerTrigger" class="org.alfresco.util.TriggerBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>org.alfresco.repo.node.index.IndexRecoveryJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="indexRecoveryComponent">
<ref bean="indexTrackerComponent" />
</entry>
</map>
</property>
</bean>
</property>
<!-- Start after 5 minutes of starting the repository -->
<property name="startDelay">
<value>300000</value>
</property>
<!-- Repeat every 10 seconds -->
<property name="repeatInterval">
<value>10000</value>
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
</bean>
<bean
id="indexTrackerComponent"
class="org.alfresco.repo.node.index.IndexRemoteTransactionTracker"
parent="indexRecoveryComponentBase">
<property name="remoteOnly">
<value>true</value>
</property>
</bean>
</beans>
[edit] /alf/alfy/WEB-INF/classes/alfresco/extension/web-client-config-custom.xml
This enables the multi-lingual features and overriding email address and max search results. This is also where custom aspects will be added.
vi
<alfresco-config>
<!-- Example of overriding the from email address -->
<config>
<client>
<from-email-address>[!ALFRESCO_ADMIN_EMAIL_ADDRESS]</from-email-address>
<search-max-results>300</search-max-results>
</client>
</config>
<!-- Example of adding languages to the list in the login page -->
<config evaluator="string-compare" condition="Languages">
<languages>
<language locale="ca_ES">Catalan</language>
<language locale="da_DK">Danish</language>
<language locale="de_DE">German</language>
<language locale="es_ES">Spanish</language>
<language locale="el_GR">Greek</language>
<language locale="fr_FR">French</language>
<language locale="it_IT">Italian</language>
<language locale="ja_JP">Japanese</language>
<language locale="nl_NL">Dutch</language>
<language locale="pt_BR">Portuguese (Brazilian)</language>
<language locale="ru_RU">Russian</language>
<language locale="fi_FI">Finnish</language>
<language locale="tr_TR">Turkish</language>
<language locale="zh_CN">Simplified Chinese</language>
</languages>
</config>
</alfresco-config>
[edit] /alf/alfy/WEB-INF/classes/alfresco/ehcache-default.xml =
In preparation for Alfresco in a cluster the cache mechanism must be set to synchronize with other members. Thankfully with the EHCache and multicasting the servers can join/exit without always re-configuring. Cache synchronization allows changes conducted on one Alfresco server to be evident on the other member servers. So, in the highly unlikely event that the same user is logged on to two seperate Alfresco instances, any changes in the users state will be reflected on all member servers. (There is a slight update delay but hardly noticable.)
Cache Synchronization is TIME SENSITIVE! Make sure that the member servers have a precise time agreement between them. I'll assume that NTP is configured and running on each respective server.
@@ -3,294 +3,658 @@
<!-- defaults -->
<diskStore
path="java.io.tmpdir"/>
-<!--
+
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
- properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
+ properties="peerDiscovery=automatic, multicastGroupAddress=233.128.128.13,
multicastGroupPort=4446"/>
<cacheManagerPeerListenerFactory
- class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
--->
+ class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
+ properties="port=40001, socketTimeoutMillis=90000"/>
+
<defaultCache
maxElementsInMemory="5000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
- overflowToDisk="false"
- >
-<!--
+ overflowToDisk="false" >
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
- properties="replicateAsynchronously=false, replicatePuts=false,
+ properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false,
replicateRemovals=true"/>
--->
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+
+
</defaultCache>
<!-- Hibernate usage -->
<cache
name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 0.4MB memory required -->
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="2000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 40MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 0.1 MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.QNameEntityImpl"
maxElementsInMemory="100"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 40MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeStatusImpl"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 15MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.aspects"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.properties"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 250MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.ChildAssocImpl"
maxElementsInMemory="200000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- general use node associations are not common -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeAssocImpl"
maxElementsInMemory="5000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- low numbers of objects expected -->
<cache
name="org.alfresco.repo.domain.hibernate.StoreImpl"
maxElementsInMemory="100"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- version counters -->
<!-- approx 0.4MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.VersionCountImpl"
maxElementsInMemory="100"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 0.1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.AppliedPatchImpl"
maxElementsInMemory="100"
timeToLiveSeconds="300"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- Permission related caches -->
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
maxElementsInMemory="1000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl.entries"
maxElementsInMemory="1000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 5MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl"
maxElementsInMemory="5000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbPermissionImpl"
maxElementsInMemory="500"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAuthorityImpl"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- approx 5MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAuthorityImpl.externalKeys"
maxElementsInMemory="5000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- Audit caches -->
<cache
name="org.alfresco.repo.audit.hibernate.AuditConfigImpl"
maxElementsInMemory="2"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.audit.hibernate.AuditDateImpl"
maxElementsInMemory="2"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.audit.hibernate.AuditSourceImpl"
maxElementsInMemory="2000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- Attribute Service Caches. -->
<cache
name="org.alfresco.repo.attributes.AttributeImpl"
maxElementsInMemory="5000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.attributes.ListEntryImpl"
maxElementsInMemory="2000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.attributes.MapEntryImpl"
maxElementsInMemory="2000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.attributes.GlobalAttributeEntryImpl"
maxElementsInMemory="1000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<!-- AVM caches -->
<cache
name="org.alfresco.repo.avm.AVMNodeImpl"
maxElementsInMemory="5000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.AVMStoreImpl"
maxElementsInMemory="100"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.VersionRootImpl"
maxElementsInMemory="200"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.ChildEntryImpl"
maxElementsInMemory="10000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.HistoryLinkImpl"
maxElementsInMemory="200"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.MergeLinkImpl"
maxElementsInMemory="200"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ properties="replicateAsynchronously=true, replicatePuts=true,
+ replicateUpdates=true, replicateUpdatesViaCopy=true,
+ replicateRemovals=true"/>
+
+ <bootstrapCacheLoaderFactory
+ class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
+ properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/>
+ </cache>
<cache
name="org.alfresco.repo.avm.AVMNodePropertyImpl"
maxElementsInMemory="2000"
eternal="true"
- overflowToDisk="false"
- />
+ overflowToDisk="false">
+ <cacheEventListenerFactory
+ class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
+ 