This is a guide for system administrators who want to install and maintain Tigase Jabber/XMPP server.
Tigase Jabber/XMPP Server is Open Source and Free (GPLv3) Java based server. The goals behind the design and implementation of the server are:
By robust and reliable server I mean the server which can handle many concurrent requests/connections and can run for a log time. By many concurrent requests/connections I mean as many as it is needed. The server is designed and implemented to handle milions of simultaneous connections.
It is not enough however to design and implement high load server and hope it will run well. The main focus in the project is put in tests. Tests are taken so seriously that dedicated testing framework has been implemented. All server functions are considered as implemented only when they pass testing cycle. The testing cycle consists of 3 fundamental tests:
There are a few elements of the security related to Jabber/XMPP server: secure data transmissions which is met by the implementation of SSL or TLS protocol, secure user authorization which is met by the implementation of DIGEST or SASL user authorization and secure deployment which is met by component architecture.
Secure deployment is a software installation which doesn't impact network security. Companies usually have their networks divided into 2 parts: DMZ which is partially open to outside world and Private network which is closed to outside world.
If the Jabber/XMPP server have to provide effective way of communication between company employees regardless they are in company office or outside (perhaps at customer site) it needs to accept connections from outside world. So the natural place for server deployment is a DMZ part. There is an issue however with such installation. Each company has normally established network users base and integrated authorization mechanisms. So it would be very good if Jabber server could use this mechanisms for users authorizations as well. Usually, however, authorization information is not available in DMZ and it shouldn't be.
Tigase server offers solution for such case. With it's component structure it can be easily deployed on any number machines and from the user point of view it is seen as a one logical Jabber server. So in our case we can install Session Manager module in private network part and Client Connection Manager with Server Connection Manager in DMZ.
Session Manager connects to DMZ and receives all packets from users. Thus is can securely realize users authorization based on company authorization mechanisms.
Architecture based on components allows you to run selected modules on separate machines so the server can be easily applied to all scenarios.
For simple installation server generates config file which can be used almost stright away with very few modifications or sometimes even no config editing is required. For complex deployments though you can tweak configuration to your needs and setup Jabber server on as many physical machines as you need.
The world changes all the time so people needs change as well. Jabber/XMPP protocol has been designed to be extensible to make it easy adding new features and apply it to different needs. As a result Jabber is a very effective platform not only for sending messages to mates. It can also be extended for sending instant notifications about events, it can be useful platform for on-line customer service, voice communication and all other cases where sending information instantly to other people is needed.
Tigase server has been designed to be extensible as well. Of course modular architecture makes it extensible as you can easily replace component which doesn't fullfill your requirements with another one better fitting your needs. But this is not all. Another factor of extensibility is how easy is to replace component or add new extensions. The great focus has been put in server design API to make it easy for other software developers to create extensions and implement new features.
Complex computer networks consisting of many servers with different services are hard to maintain. There is no other way than employing professional staff and looking after the network.
Not all networks are so complex however. Most small companies have just a few servers for their needs with services like e-mail, HTTP server with company website and that's it. They might want to add Jabber server to the collection of their services and don't want to dedicate much resources on setting it up and later maintenance. For such users default configuration is pretty much what they need. If operating system on the server is well configured then Tigase should pickup correct hostname.
Tigase server is designed and implemented to allow dynamic reconfiguration at runtime so there is no need for restarting server each time you want to change a configuration settings.
There are also interfaces and handlers available to make it easy to implement web user interface for server monitoring and configuring. Such user interface will included in one of future releases.
This section keeps set of documents which apply to all the Tigase server version and contain more generic or introductory information.
Configuration settings are kept in XML file very similar in it's structure to Java 5.0 preferences file. The most significant difference is possibility to assign multiple values to one key (entry). Another difference is that in configuration file all values are uu-encoded so it is possible to keep different data in configuration even if they could cause xml parsing errors.
If you need sample configuration file containing all used defaults just run server in usual way. If configuration file can not be found it is created with default settings. And even if there is an old configuration file with some settings missing server automatically adds missing entries at startup time.
If you look inside configuration file you can see that this is just normal XML file with a few top-level separate sections. These sections are called components.
This is it. Tigase server consists of components and without components there is no application at all. This is why the only configuration settings you can find there are only under some component level.
More precisely top level element in this XML file is called: <tigase-config/> and it doesn't contain any top level configuration settings.
Under the top level element there are at least 2 or more <component/> elements. Each component can be distinguished from others by it's 'name'. That is, 'name' attribute is mandatory and must be distinct within configuration file. It is just component ID. Each component can be named any way you like it doesn't need to mean anything. It is just easier to manage configuration if you select sensible names.
<component/> elements keep configuration settings for server modules.
Example 1:
<tigase-config>
<component name="basic-conf">
.... settings
</component>
<component name="message-router">
.... settings
</component>
</tigase-config>Configuration settings are kept in "simple" maps like structures (key, values, type) triplets.
String. Other possible types are: Boolean, Integer, Long and corresponding array types: String[], Boolean[], int[], long[].Configuration settings are stored in <map/> element which contains list of <entry/> elements. If there are multiple values for a parameter they are stored as a list of <item> elements.
Example 2:
<map>
<entry value="localhost" type="String" key="remote-host"/>
<entry value="false" type="Boolean" key="demo-mode"/>
<entry value="1000" type="Integer" key="max-queue-size"/>
<entry type="String[]" key="hostnames">
<item value="test-a"/>
<item value="localhost"/>
</entry>
<entry type="int[]" key="ports">
<item value="5222"/>
<item value="5223"/>
</entry>
</map>
Configuration settings can be organised hierarchically using <node> elements:
Example 3:
<component name="c2s">
<map>
<entry type="String[]" key="hostnames">
<item value="test-d"/>
<item value="localhost"/>
</entry>
</map>
<node name="connections">
<map>
<entry type="int[]" key="ports">
<item value="5222"/>
<item value="5223"/>
</entry>
</map>
<node name="5222">
<map>
<entry value="localhost" type="String" key="remote-host"/>
<entry value="plain" type="String" key="socket"/>
<entry value="accept" type="String" key="type"/>
</map>
</node>
</node>
</component>Detailed description for all possible settings is split to per-component chapter. Please look for particular component description for details.
Options you most likely have to change at deployment time are:
Please let me know if you think more options should be described here.
At the moment the only way to change configuration is to manually edit XML config file. So be prepared for tough times. The good news it that more user friendly interfaces are scheduled for next release. And it will be also reconfigure server at runtime without need to restart service.
This is the most likely thing to change after you install server and generate default configuration. Actually it is also the easiest option to customize.
Open tigase-config.xml in you favorite text editor and search for string: "admins". You should find section looking like this:
<entry type="String[]" key="admins">
<item value="admin%40your.hostname.com"/>
<item value="admin%40localhost"/>
</entry>Characters "%40" stand for '@'. So assuming you have just 1 admin account on your installation which is: "frank@jabber.example.com" you need to replace above code with:
<entry type="String[]" key="admins">
<item value="frank%40jabber.example.com"/>
</entry>And yes, you can just remove second entry with admin account: "admin@localhost" unless you really want to keep it. Be aware though all system messages will be sent to ALL admin accounts.
Well, if the account does not exists the message is discarded and a warning is be printed in log file. Again, read it again, the previous sentence...
It means that the admin account has to be also created in normal way on the Jabber server. Just register it using your Jabber client. The admin accounts setting works just as a forward instruction. So as a result all system and admin messages are forwarded to all admin accounts if they exist.
Obviously you can have admin accounts as many as you like:
<entry type="String[]" key="admins">
<item value="frank%40jabber.example.com"/>
<item value="lucy%40jabber.example.com"/>
<item value="mark%40jabber.example.com"/>
<item value="brenda%40jabber.example.com"/>
<item value="luck%40jabber.example.com"/>
</entry>This one might be a little bit more tricky than previous as hostnames setting has to be changed in a few places. Don't ask why now as this is "Short configuration guide", you remember. Here we focus on how not on why.
You have to search configuration file for string "hostnames". There are more than one such sections and you have to find ALL sections looking like:
<entry type="String[]" key="hostnames">
<item value="your.hostname.com"/>
<item value="localhost"/>
</entry>It may also look like:
<entry type="String[]" key="hostnames">
<item value="localhost"/>
</entry>Depending how successful was mechanism for automatic hostname detection. It of course does not depends on your luck. It depends on network configuration on your server.
The first form is more useful as it includes also hostname recognized in network environment. If it is correct then you can just leave it as it is. If it is incorrect you have to change it. Please remember, if you want your server to be able to communicate with other Jabber/XMPP servers the hostname you put there must resolve in DNS to your Jabber server machine IP address. In other words. If you try to connect from the Internet to machine with this hostname the connection should reach your Jabber server.
And remember your Jabber server users' JIDs (Jabber IDs) can include only those hostnames which are included in the configuration. So for our case you can use only JIDs: "user2@your.hostname.com", "user1@your.hostname.com" and so on.
If you server have more Internet addresses (virtual domains) assigned to it your Jabber server can use them all. So your configuration may look like:
<entry type="String[]" key="hostnames">
<item value="your.hostname.com"/>
<item value="clien1.hostname.com"/>
<item value="another.hostname.com"/>
<item value="jabber.sample-domain.com"/>
<item value="jabber.some-project.org"/>
<item value="localhost"/>
</entry>In such case users' JIDs on your Jabber server may include any of defined above domains like: "user1@your.hostname.com", "user1@clien1.hostname.com", "user1@jabber.sample-domain.com". Each of these 3 sample JIDs refer to different user account.
Your server will accept connections only for domains defined in configuration file.
In majority cases it does not matter whether you leave "localhost" or remove it. It is sometimes better to leave it though. So if you are not sure if you can remove it in your environment just leave it as is.
Logging mechanism is very flexible in Tigase server. You can adjust separate logging level for each single component. You can also direct loggin to many different destinations like console, file, network socket and so on. Unfortunately it also mean it is a bit complex. The general idea however is quite simple so once you understand it it shouldn't be difficult for you anymore. This guide however describes logging very briefly. Loot at full configuration documentation for detailed explanation.
In standard sever configuration you usually want to turn off all logging to console and all warning and more serious notices directed to log file. Let's say logs will be written to /var/log/tigase-server.log which shouldn't get bigger than 10MB and 5 old logs will be preserved. Here are instructions how to set options.
Open tigase-config.xml in you favorite text editor and search for string: "logging". You should find section looking like this:
<node name="logging">
<map>
<entry value="FINE" type="String" key=".level"/>
<entry value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler" type="String" key="handlers"/>
<entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.ConsoleHandler.formatter"/>
<entry value="WARNING" type="String" key="java.util.logging.ConsoleHandler.level"/>
<entry value="true" type="String" key="java.util.logging.FileHandler.append"/>
<entry value="5" type="String" key="java.util.logging.FileHandler.count"/>
<entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.FileHandler.formatter"/>
<entry value="ALL" type="String" key="java.util.logging.FileHandler.level"/>
<entry value="100000" type="String" key="java.util.logging.FileHandler.limit"/>
<entry value="logs%2Ftigase.log" type="String" key="java.util.logging.FileHandler.pattern"/>
<entry value="true" type="String" key="tigase.useParentHandlers"/>
</map>
</node>Assuming we make this guide easy and strightforward let me show how this section should look like after modification. So you could just copy and paste it to your config file without going into details. After the configuration code I will briefly explain what each line means so you should be able to further adjust settings for your needs.
<node name="logging">
<map>
<entry value="WARNING" type="String" key=".level"/>
<entry value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler" type="String" key="handlers"/>
<entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.ConsoleHandler.formatter"/>
<entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.FileHandler.formatter"/>
<entry value="OFF" type="String" key="java.util.logging.ConsoleHandler.level"/>
<entry value="true" type="String" key="java.util.logging.FileHandler.append"/>
<entry value="5" type="String" key="java.util.logging.FileHandler.count"/>
<entry value="ALL" type="String" key="java.util.logging.FileHandler.level"/>
<entry value="10000000" type="String" key="java.util.logging.FileHandler.limit"/>
<entry value="%2Fvar%2Flog%2Ftigase-server.log" type="String" key="java.util.logging.FileHandler.pattern"/>
<entry value="true" type="String" key="tigase.useParentHandlers"/>
</map>
</node>Each line explained:
<entry value="WARNING" type="String" key=".level"/>
Effectively we set WARNING level for all possible logs for all possible components. So more detailed logging information will be discarded. All possible log levels are: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL.
<entry value="java.util.logging.ConsoleHandler+java.util.logging.FileHandler" type="String" key="handlers"/>
We set 2 handlers for logging information: console and file handler. As we are going to turn off logging to console we could remove all configuration settings for console handler as well. It would simplify configuration file. I don't recommend it though. If there are any problems with your installation switching console logging on might be very helpful and if you remove these settings from config file it may be difficult to bring them back. Hm... maybe not with such excellent documentation.... ;-)
<entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.ConsoleHandler.formatter"/> <entry value="tigase.util.LogFormatter" type="String" key="java.util.logging.FileHandler.formatter"/>
We set here log formatter for console and file handler. Standard Java handlers print each log message in 2 lines. Tigase formatter prints all logging info in 1 line which make it much easier to filter logs by log type, logging component or log level or whatever you wish. You can just use simple sed command and that's it.
<entry value="OFF" type="String" key="java.util.logging.ConsoleHandler.level"/>
Here we just switch console handler off. To switch it on back set any different level from the list above.
<entry value="true" type="String" key="java.util.logging.FileHandler.append"/>
This settings is to controll whether we want to append logs into old log file or we want to create new log file (removing old content) each time server is restarted.
<entry value="5" type="String" key="java.util.logging.FileHandler.count"/>
Sets number of old log files to preserve to 5.
<entry value="ALL" type="String" key="java.util.logging.FileHandler.level"/>
This line sets the logging level for file handler. Here we set that we want all possible logs to be written to the file. The global level setting however says that only WARNING logs will be generated. So if you want to have more detailed logs you need to adjust global logging level.
<entry value="10000000" type="String" key="java.util.logging.FileHandler.limit"/>
Log file maximum size set to 10MB. After reaching this size the log file is closed and new file is created.
<entry value="%2Fvar%2Flog%2Ftigase-server.log" type="String" key="java.util.logging.FileHandler.pattern"/>
Location of the log file and file name: /var/log/tigase-server.log. Please note %2F instead of '/' character.
<entry value="true" type="String" key="tigase.useParentHandlers"/>
This setting requires going into more details so it is explained in comprehensive configuration guide.
If something goes wrong and you can't find out why it is not working as you expect you might want more detailed debugging options switched on.
Tigase is a Java application and it uses Java logging library this gives you flexibility to switch logging on for selected java package or even for a single Java class.
Logs files are stored in logs/ directory. tigase-console.log keeps all the data but only basic logs. tigase.log.N files keep all the detailed logging entries. So this is the place where you should look in case of problems.
The easiest way to change logging for the Tigase package is modifying in init.properies following line:
--debug=server
The line above says: "Switch on ALL debug messages for packet: tigase.server". The tigase.server packet keeps all component's classes. So it allows you to monitor what is going on in each component. What packets it receives and what it is sending out.
Usually people want to see what is going on the network level. That is what has been sent and what has been received by the server - the actual character data. The class which would print all received and sent character data is: tigase.xmpp.XMPPIOService. To enable all debugging info for this class you have to modify the debug line:
--debug=xmpp.XMPPIOService
Note, you skip the tigase. part.
You can also have debugging switched on for many packages/classes at the same time:
--debug=server,xmpp.XMPPIOService
Other packages you might be interested in are:
tiagse.io and tigase.net which can print out what is going on a very low level network level including TLS/SSL stuff.tigase.xml would print the XML parser debugging data.tigase.cluster would print all the clustering related stuff. So if you have clustered installation you might be interested in debug settings:--debug=server,cluster
tigase.xmpp.impl would print logs from all plugins loaded to the Tigase server.
and so on...
This method, however has 2 main disadvantages:
tigase. package. And this might be a problem if you include your own code in and load it into the server.If you want to modify debugging settings without regenerating the whole XML config file you can modify it yourself manually and add debug entries. This must be done very carefully or you break the XML file and configuration won't work.
Anyway. Open the XML config file with some good text editor (or XML editor) and find the line:
<node name="logging">
Below is a long list of all logging settings. One of them is:
<entry value="INFO" type="String" key=".level"/>
Which says: INFO debug level for all the code. This level gives you very little debugging information. Therefore for example your init.properties line --debug=server adds one extra line in there:
<entry value="ALL" type="String" key="tigase.server.level"/>
I think now everything should be clear. You need to add a similar line changing only "key" attribute. If you need to switch logging on for a specific class - tigase.xmpp.XMPPIOService for example, add:
<entry value="ALL" type="String" key="tigase.xmpp.XMPPIOService.level"/>
You can also put there your own package or class name. After you changed the config file you have to restart the server.
Note, don't overdose the debugging or your logs are full of trash you can read.
You can easily copy data between Tigase compatible repositories that is repositories for which there is a database connector. It is not that easy however to import data from an external source. Therefore a simple data import functionality has been added to repository utilities package.
You can access repository utilities through command ./bin/repo.sh or ./scripts/repo.sh depending on whether you use binary package or source distribution.
-h parameter gives you a list of all possible parameters:
./scripts/repo.sh -h
Parameters:
-h this help message
-sc class source repository class name
-su uri source repository init string
-dc class destination repository class name
-du uri destination repository init string
-dt string data content to set/remove in repository
-u user user ID, if given all operations are only for that ID
if you want to add user to AuthRepository parameter must
in form: "user:password"
-st perform simple test on repository
-at simple test for adding and removing user
-cp copy content from source to destination repository
-pr print content of the repository
-n data content string is a node string
-kv data content string is node/key=value string
-add add data content to repository
-del delete data content from repository
------------
-roster check the user roster
-aeg [true|false] Allow empty group list for the contact
-import file import user data from the file of following format:
user_jid, password, roser_jid, roster_nick, subscription, group
Note! If you put UserAuthRepository implementation as a class name
some operation are not allowed and will be silently skipped.
Have a look at UserAuthRepository to see what operations are
possible or what operation does make sense.
Alternatively look for admin tools guide on web site.
The most critical parameters are source repository class name and initialization string. Therefore there are a few example, preset parameters which you can use an example and adjust for your system. If you look inside the repo.sh script you can find at the end of the script following lines:
XML_REP="-sc tigase.db.xml.XMLRepository -su ../testsuite/user-repository.xml_200k_backup" MYSQL_REP="-sc tigase.db.jdbc.JDBCRepository -su jdbc:mysql://localhost/tigase?user=root&password=mypass" PGSQL_REP="-sc tigase.db.jdbc.JDBCRepository -su jdbc:postgresql://localhost/tigase?user=tigase" java $D -cp $CP tigase.util.RepositoryUtils $MYSQL_REP $*
You can see that the source repository has been set to MySQL database with tigase as the database name, root the database user and mypass the user password.
You can adjust these settings for your system.
Now to import data to your repository simply execute the command:
./bin/repo.sh -import import-file.txt
Note, the import function is available from b895
The format of the import file is very simple. This is a flat file with comma separated values:
jid,password,roster_jid,roster_nick,subscriptio,group
To create such a file from MySQL database you have to execute command like this one:
SELECT a, b, c, d INTO OUTFILE 'import-file.txt' FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' FROM test_table;
This guide describes how to prepare the MySQL database for connecting the Tigase server to it.
The MySQL database can be prepared in many ways. Most of Linux distributions contain tools which allow you to go through all steps from the shell command line. To make sure, however it works on all platforms the same way I show first how to do it under MySQL command line client.
Run the MySQL command line client in either Linux or MS Windows environment and enter following instructions:
mysql> create database tigasedb;
tigase_user user and grant him access to the tigasedb database. Depending on how you plan to connect to the database (locally or over the network) use one of following commands or all if you are not sure:
mysql> GRANT ALL ON tigasedb.* TO tigase_user@'%'
IDENTIFIED BY 'tigase_passwd';
Grant access to tigase_user connecting from localhost.
mysql> GRANT ALL ON tigasedb.* TO tigase_user@'localhost'
IDENTIFIED BY 'tigase_passwd';
Grant access to tigase_user connecting from local machine only.
mysql> GRANT ALL ON tigasedb.* TO tigase_user
IDENTIFIED BY 'tigase_passwd';
For the Tigase server version 4.x additional permissions must be granted for the database user:
mysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user'@'localhost'; mysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user'@'%'; mysql> GRANT SELECT, INSERT, UPDATE ON mysql.proc TO 'tigase_user';
And now you can update user permission changes in the database:
mysql> FLUSH PRIVILEGES;
mysql> use tigasedb;
Assuming you run the mysql client in Linux from the Tigase installation directory. If you run the Tigase server all versions below 4.0:
mysql> source database/mysql-schema.sql;
For the Tigase server version 4.x you have to use proper schema version:
mysql> source database/mysql-schema-4.sql;
On Windows you have probably to enter the full path:
mysql> source c:/Program Files/Tigase/database/mysql-schema.sql;
The initialization schema file should be also available locally in database/ directory of your Tigase installation.
Follow steps below to prepare the MySQL database:
mysqladmin -p create tigasedb
tigase_user user and grant him access to the tigasedb database. Depending on how you plan to connect to the database (locally or over the network) use one of following commands or all if you are not sure:
echo "GRANT ALL ON tigasedb.* TO tigase_user@'%' \
IDENTIFIED BY 'tigase_passwd'; \
FLUSH PRIVILEGES;" | mysql -u root -pdbpass mysql
Grant access to tigase_user connecting from localhost.
echo "GRANT ALL ON tigasedb.* TO tigase_user@'localhost' \
IDENTIFIED BY 'tigase_passwd'; \
FLUSH PRIVILEGES;" | mysql -u root -pdbpass mysql
Grant access to tigase_user connecting from local machine only.
echo "GRANT ALL ON tigasedb.* TO tigase_user \
IDENTIFIED BY 'tigase_passwd'; \
FLUSH PRIVILEGES;" | mysql -u root -pdbpass mysql
mysql -u dbuser -p tigasedb < mysql-schema.sql
For the Tigase server version 4.0 and later:
mysql -u dbuser -p tigasedb < mysql-schema-4.sql
The initialization schema file should be also available locally in database/ directory of your Tigase installation.
To allow secure connections through SSL or TLS channel you need SSL certificate.
The main purpose of SSL certificate is to provide connecting entity with a proof of identity of your server. Significant role in proving identity of your server plays trusted third party - usually the issuer of the certificate.
Certificate issued by trusted third party usually cost you a money. You can also use self signed certificate which works as well but gives authentication warning on client software at the connecting time.
Tigase server binary package and sources repository contain so called "dummy" certificate which doesn't refer to any real site name. This certificate is temporary. Should be used only for initial testing of your server. It should be replaced with real one as soon as possible. By real certificate I mean either self signed certificate or issued by trusted third party organization.
Here are instructions how to install real certificate for Tigase server.
Please note! You have to use keytool program included in JDK-1.6 or later version. The utility included in earlier versions can not import third party signed certificates correctly.
If you don't have third party signed certificate you should generate self-signed certificate.
Some clients don't works correctly with DSA keys, so we need to use RSA algorithm. To generate private and public keypair you should use keytool:
keytool -genkey -alias yourdomain -keystore rsa-keystore \
-keyalg RSA -sigalg MD5withRSA
Where yourdomain is a domain part of JIDs on your Jabber/XMPP server. If you want to have TLS support for virtual domains you have to create certificate for each virtual domain. If you have just one domain or for some reason you have to use one certificate for all domains use default as an alias.
Now, enter the secret password to protect keystore:
Enter keystore password: 123456
The keytool asks several questions about certificate data. First question is very important! You must enter a hostname of your XMPP server!!
What is your first and last name? [Unknown]: jabber.myserver.org What is the name of your organizational unit? [Unknown]: What is the name of your organization? [Unknown]: What is the name of your City or Locality? [Unknown]: What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: Is CN=jabber.myserver.org, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct? [no]: yes
In last step you can enter password for key. At the moment different password for keystore and key is not supported so you have to enter the same password here as for keystore.
Enter key password for <mykey>
(RETURN if same as keystore password):
Now you have to copy file rsa-keystore to directory certs/ in your tigase server installation. The file could also be installed in different location but then corrections to config file are required. Refer to configuration documentation for details.
If you don't have third-party signed certificate yet but you want to have one you could obtain it from cacert.org for free.
First, you have to generate Certificate Request:
keytool -certreq -alias yourdomain -keystore rsa-keystore
Where yourdomain is a domain name for which this certificate is generated. If you need support for multiple virtual domains you need to have certificate for each domain separately and assign proper alias to certificate. If you have just one domain or for some reason you have to use one certificate for all domains use default as an alias.
Keytool generates the request:
-----BEGIN NEW CERTIFICATE REQUEST----- MIIBrzCCARgCAQAwbzEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UE BxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjETMBEGA1UEAxMK c2VydmVyLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs73Y70725OcG0j4kpCfDX59e qhz2gdGOO0LyMO7rm4m+ZCenq8E88M0RJ8/LV/7q0mtOAzbI8dtXZnmJ74xihCH8ZTFpVDMyFWgk WCj2kz+IUD9vWt6i1UepSkr1a/jYmVMN3RSaoS+j+QLBsJ4rWeOHgIdbiF5tnMhoZMXU//0CAwEA AaAAMA0GCSqGSIb3DQEBBAUAA4GBAHY5r9rftqiKESbbkCcfVhvnUqN4aMTC8/zXWwzBX8guC0kd H46+p6eizwJg6p+h6rqShG2OqXCPrJzO3buHr1jEWRTlB8l5CM53L/xq61nYuaSf5R7Vv/RX2+aD JyoBqYIoSUED0+Sjhej0SUPTOdpA/bfnqdfdtckday4vsLPC -----END NEW CERTIFICATE REQUEST-----
Now send the request to your CA. CA issues a signed certificate and send it to you. It may may look like:
-----BEGIN CERTIFICATE----- MIICUDCCAbkCBEUqAK0wDQYJKoZIhvcNAQEEBQAwbzEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UE CBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMH VW5rbm93bjETMBEGA1UEAxMKc2VydmVyLm9yZzAeFw0wNjEwMDkwNzU2MjlaFw0wNzAxMDcwNzU2 MjlaMG8xEDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vua25v d24xEDAOBgNVBAoTB1Vua25vd24xEDAOBgNVBAsTB1Vua25vd24xEzARBgNVBAMTCnNlcnZlci5v cmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALO92O9O9uTnBtI+JKQnw1+fXqoc9oHRjjtC 8jDu65uJvmQnp6vBPPDNESfPy1f+6tJrTgM2yPHbV2Z5ie+MYoQh/GUxaVQzMhVoJFgo9pM/iFA/ b1reotVHqUpK9Wv42JlTDd0UmqEvo/kCwbCeK1njh4CHW4hebZzIaGTF1P/9AgMBAAEwDQYJKoZI hvcNAQEEBQADgYEAQqRPdkbc/pdDcPIWOThn2XPp0gitPkXq89ZM1mb0Pib1OISj9ekjqhEZz0UA cI6g1XttpY6hKi6Gg+mRbwiHNVebkDLamE2UIcVJ1wBtowYeOcV1CcLnlj91ScMKNhfD5ebQL+be tWWrJX3ep+80kF/NdVkc7htGOhLebopp8SQ= -----END CERTIFICATE-----
You should save the Certificate to disk file.
If you already have third-party sgined certificate you have to import it with keytool program to server certificate storage.
Note! You must have a root CA certificate!!! You can download the cert from CA (ie.: root.crt) and import:
keytool -import -keystore rsa-keystore -file root.crt \
-alias root
Last step is import Certificate to your keystore:
keytool -import -alias yourdomain -keystore rsa-keystore \
-file your-certificate.cer
Where yourdomain is a domain name for which this certificate has been generated. If you need support for multiple virtual domains you have to import certificate for each domain separately and assign proper alias to certificate. If you have just one domain or for some reason you have to use one certificate for all domains use default as an alias.
It's also good to import root CA certificate to this keystore. You must find it on CA website.
keytool -import -keystore rsa-keystore -file rootCA.cer
It may also happen that you have generated certreq using openssl for use in other services like WWW. In such case you may have your private key and certificate in separate files. Let's say private key is in ssl.key file and certificate is in ssl.crt file. To put them together use following command:
openssl pkcs12 -export -inkey ssl.key -in ssl.crt \
-out mycert.pfx -name "default"And now you can load certificate with private key to your keystore:
keytool -importkeystore -srckeystore mycert.pfx \
-srcstoretype pkcs12 -destkeystore rsa-keystore \
-srcalias default -destalias yourdomain \
-destkeypass your_keystore_passNote! Please note -destkeypass parametr. Your keys password must be the same as keystore password. Otherwise it won't work.
Now you have to copy file rsa-keystore to directory certs/ in your tigase server installation. The file could also be installed in different location but then corrections to config file are required. Refer to configuration documentation for details.
The final note - don't forget to modify tigase server configuration file and set proper password for your keystore.
This is a component which make it easier to integrate Jabber/XMPP server with other, third-party tools.
It simply allows you to send stanzas from your application without implementing any Jabber/XMPP specific code. The component regularly reads specified data source for XMPP packets to send. The data source can be an SQL database, directory on your filesystem or anything you might want.
If you have Web application for example which you want to send notifications of any event to selected users you can install StanzaSender component on your Tigase server. It will help you to easily distribute your messages to end-users.
The module itself doesn't do anything. It just schedules tasks and sends stanzas which come from... it doesn't know. To do actual work of retrieving stanzas from data source the component uses tasks.
In theory the task can retrieve XMPP packets for sending from any location or may just generate stanzas on its own.
In practise there are 2 tasks already implemented and ready to use. You can treat them as a sample code for implementation of your own tasks customised for your specific needs or you can just use these tasks as they are.
The tasks which are available are:
FileTask retrieving stanzas from directory in file system.JDBCTask retrieving stanzas from SQL database.FileTask implements tasks for cyclic retrieving stanzas from a directory and sending them to the StanzaHandler object.
It looks for any new stanza to send. Any single file can contain only single stanza to send and any entry in database table can also contain only single stanza to send. File on hard disk and record in database is deleted after it is read.
Any file in given directory is treated the same way - Tigase assumes it contains valid XML data with XMPP stanza to send. You can however set in configuration, using wildchars which files contain stanzas. All stanzas must contain complete data including correct "from" and "to" attributes.
By default it looks for *.stanza files in /var/spool/jabber/ folder but you can specify different directory name in initialization string. Sample initialization strings:
/var/spool/jabber/*.stanza
/var/spool/jabber/*
The last is equal to:
/var/spool/jabber/
Note the last forward slash '/' is required in such case if the last element of the path is a directory.
Please note! Tigase must have writing permissions for this directory, otherwise it may not function properly.
JDBCTask implements tasks for cyclic retrieving stanzas from database and sending them to the StanzaHandler object.
Database table format:
Any record in this table is treated the same way - Tigase assmes it contains valid XML data with XMPP stanza to send. No other data are allowed in this table. All stanzas must be complete including correct "from" and "to" attriutes.
By default it looks for stanzas in xmpp_stanza table but you can specify different table name in connection string. Sample connection string:
jdbc:mysql://localhost/tigasedb?user=tigase&
password=pass&table=xmpp_stanza
Please note the last parameter which is specific to JDBCTask. You can specify the table name which stores stanzas for sending. If omitted default value is: xmpp_stanza.
It is Tigase component so the configuration is similar to configuration of all other components. The simplest way to get the settings for StanzaSender is by generating configuration with all possible components. To do this you have to run Tigase server with --gen-config-all parameter set.
By default this component name is ssend and here is a content of the configuration file for StanzaSender:
It is one of msg-receivers:
<entry type="String[]" key="id-names"> ... <item value="ssend"/> </entry>
To activate the component and specify class name for it following entries has been added:
<entry value="true" type="Boolean" key="ssend.active"/> <entry value="tigase.server.ssender.StanzaSender" type="String" key="ssend.class"/>
And the main settings section for the component:
<component name="ssend">
<map>
<entry value="10" type="Long" key="default-interval"/>
<entry value="1000" type="Integer" key="max-queue-size"/>
<entry type="String[]" key="stanza-listeners">
<item value="jdbc"/>
<item value="file"/>
</entry>
</map>
<node name="file">
<map>
<entry value="true" type="Boolean" key="active"/>
<entry value="tigase.server.ssender.FileTask" type="String" key="class-name"/>
<entry value="%2Fvar%2Fspool%2Fjabber%2F*.stanza" type="String" key="init-string"/>
<entry value="10" type="Long" key="interval"/>
</map>
</node>
<node name="jdbc">
<map>
<entry value="true" type="Boolean" key="active"/>
<entry value="tigase.server.ssender.JDBCTask" type="String" key="class-name"/>
<entry value="jdbc%3Amysql%3A%2F%2Flocalhost%2Ftigase%3Fuser%3Dtigase%26password%3Dmypass%26table%3Dxmpp_stanza" type="String" key="init-string"/>
<entry value="10" type="Long" key="interval"/>
</map>
</node>
</component>I think most of parameters should be pretty clear but some may need a little explanation. General StanzaSender parameters:
Each task has own, separate parameters list. For each task from the stanza-listeners list there is a separate section with parameters for each task:
tigase.server.ssender.SenderTask and it is loaded at runtime.FileTask allows you to use wild-chars in directory/ file name specification and JDBCTask allows you to specify additional parameter at the end of JDBC connection string - database table name. For specific examples look at above config sections.Any Jabber server and any transport connect with each other usually through external component protocol (XEP-0114). So all you need to do is to correctly prepare configuration for this protocol on both sides.
Continue reading to learn how to setup Tigase and PyMSN for working together...
There are a few basic parameters to set for this protocol:
/etc/hosts file.Here is side by side configuration for both applications: PyMSN-t and Tigase to make them work together. I have setup both services on my laptop which hostname is test-d. To make sure both test-d and msn.test-d resolve to correct IP address I am adding entry to /etc/hosts file:
## In your case the IP address should be probably different. 192.168.0.13 test-d msn.test-d
Tigase server connects to MySQL database (or built-in XMLBD for simpler configuration variant).
I am not going to setup PyMSN-t to run in background as a system service. This is specific to the system you use and is covered in transport documentation and you operating system. Most of systems have own scripts to start services so I would recommend to use them. Here we just run it in foreground with full logging switched on to the console to make it easier track what happens.
PyMSN-t - /etc/jabber/pymsn-t.xml file |
Tigase - etc/tigase.conf file |
|---|---|
<pymsnt>
<!-- The JabberID of the transport -->
<jid>msn.test-d</jid>
<!-- The public IP or DNS name of the machine
the transport is running on -->
<host>test-d</host>
<!-- The location of the PID file, relative
to the PyMSNt directory -->
<pid>/var/run/jabber/pymsn-t.pid</pid>
<!-- If set, the transport will background
itself when run, we don't want to do this right
now. -->
<!-- <background/> -->
<!-- The IP address of the main Jabber server
to connect to -->
<mainServer>127.0.0.1</mainServer>
<!-- The TCP port to connect to the Jabber
server on (this is the default for Jabberd2) -->
<port>5347</port>
<!-- The authentication token to use when
connecting to the Jabber server -->
<secret>secret</secret>
<lang>en</lang>
<website>http://test-d/</website>
<allowRegister/>
<getAllAvatars/>
<!-- Please give the port to listen for Jabber
socks5 transfers on. Note the standard port number
set here is 8010. This port
however is in use on my machine so this is why
I had to set it to different value.-->
<ftJabberPort>8014</ftJabberPort>
<admins>
<jid>tus@test-d</jid>
</admins>
<!-- The logging level
0 -> No logging
1 -> Log tracebacks
2 -> Log tracebacks, warnings and errors
3 -> Log everything -->
<debugLevel>3</debugLevel>
<!-- The file to log to. Leave this disabled
for stdout -->
<!-- <debugFile>debug.log</debugFile> -->
</pymsnt> |
You may consider to remove 2 last lines from TIGASE_OPTIONS variable to not use MySQL for now. Tigase will then use internal XMLDB which doesn't need any special setup. (Just remember to leave closing double quotes...)
ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
DRV="-Djdbc.drivers=com.mysql.jdbc.Driver"
CLASSPATH="${CLASSPATH}:libs/jdbc-mysql.jar"
JAVA_OPTIONS="${ENC} ${DRV} -server -Xms100M -Xmx100M "
TIGASE_CONFIG="etc/tigase-mysql.xml"
## All TIGASE_OPTIONS settings must be in single line
## They are split to make them more readable
TIGASE_OPTIONS="--gen-config-all --admins \"tus@test-d\"
--virt-hosts test-d,localhost --debug server
--ext-comp \"test-d,msn.test-d,5347,secret,plain,accept\"
--user-db mysql --user-db-uri
\"jdbc:mysql://localhost/tigase?user=tigase&password=mypass\" " |
| PyMSN-t - run command | Tigase - run command |
python /usr/lib/python2.4/site-packages/pymsn-t/pymsn-t.py -c /etc/jabber/pymsn-t.xml
|
./bin/tigase.sh start etc/tigase.conf |
| PyMSN-t - expected output | Tigase - expected output |
A few last lines should look like:
[2007-05-07 13:00:39] Starting factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> [2007-05-07 13:00:39] <twisted.internet.tcp.Connector instance at 0xb7ceb24c> will retry in 2 seconds [2007-05-07 13:00:39] Stopping factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> [2007-05-07 13:00:41] Starting factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> [2007-05-07 13:00:41] <twisted.internet.tcp.Connector instance at 0xb7ceb24c> will retry in 5 seconds [2007-05-07 13:00:41] Stopping factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> [2007-05-07 13:00:46] Starting factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> [2007-05-07 13:00:46] <twisted.internet.tcp.Connector instance at 0xb7ceb24c> will retry in 15 seconds [2007-05-07 13:00:46] Stopping factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7ce80ac> And PyMSN should continue to print such lines until it successfully connects to the Tigase server. When it happens following lines should be printed: [2007-05-07 13:29:04] Starting factory <twisted.xish.xmlstream.XmlStreamFactory instance at 0xb7cf00ac>
[2007-05-07 13:29:04] INFO :: :: :: componentConnected :: PyTransport :: {'xmlstream': <twisted.xish.xmlstream.XmlStream instance at 0xb7d0feac>, 'self': 'instance'} |
To see the log output from Tigase server execute following command:
tail -f logs/tigase-console.log After transport connects to Tigase server you should see lines like: 2007-05-07 12:29:05 ComponentConnectionManager.processHandshake() FINE: Connected to: msn.test-d 2007-05-07 12:29:05 ComponentConnectionManager.updateServiceDiscovery() FINEST: Modifing service-discovery info: <item name="XEP-0114 connected" jid="msn.test-d"/> |
Note! There was a bug in jabber:iq:register plugin which caused problems with registering account in transport. Please use build 432 or later.
In the most cases you use just one SessionManager object for your Tigase server installation. A single SM can handle multiple virtual domains with separate SSL certificates for each domain.
Sometimes, however you need very different configuration for each domain. For example you wish to use a separate database for a selected domain or you need a different set of plugins for each domain. For one domain you might want to allow user registration via XMPP and for another you might want to disable this feature. In such a case you need to load more than one session manager.
This is generally not a problem. You just need to add another component in the configuration and adjust default settings.
The question is now how Tigase server knows to which session manager it has to forward packets received from the network. Mind, there is only one component responsible for handling client connections. So it needs to know somehow which session manager is receiver for certain packet. Of course you set domain names in session manager too. But that is not enough. Tigase server supports cluster mode configuration where session manager can be running on a separate machine. So packet routings rules are not so simple to look at the domain name only. Therefore client connection manager (c2s) must know where is located the session manager responsible for handling the packet received from the network.
To solve the problem routings concept has been introduced. You can define packet routings based on the domain name set during XMPP stream initialization. Each time c2s component receives packet from the network it tries to resolve destination component for the packet based on the current routings table. If you look in you server XML configuration file and search for c2s configuration section you can find routings node. Default configuration for routings table is quite simple. Just a single regular expression:
<node name="routings">
<map>
<entry key=".+" type="String" value="sess-man%40tigase.org"/>
<entry key="multi-mode" type="Boolean" value="true"/>
</map>
</node>
As you can see this routings table forwards all packets to a single destination - session manager located on the tigase.org server.
Let's say we have now two session managers each of them is responsible for a separate domain.sm1@tigase.org handles requests for tigase.org and sm2@tigase.net handles requests for domain tigase.net. So let's modify our default configuration to properly spread the traffic between these two sessiona managers:
<node name="routings">
<map>
<entry key="tigase.org" type="String" value="sm1%40tigase.org"/>
<entry key="tigase.net" type="String" value="sm2%40tigase.net"/>
<entry key="multi-mode" type="Boolean" value="true"/>
</map>
</node>
Please remember that a key is a regular expression in Java style: Pattern.html. You can match more than a single domain with the key, for example: tigase.+ to match all domains starting with tigase. The expression, however won't match domain: xmpp.tigase.org. To match this domain the expression would need to be: .+tigase.+.
Well it is authentication against Drupal database at the moment. So it is not full integration with Drupal yet.
As Drupal keeps encrypted passwords in database the only possible authorization protocols are those based on PLAIN passwords.
To protect your passwords Tigase server must be used with SSL or TLS encryption.
Implementation of Drupal database based authorization is located in tigase.db.jdbc.DrupalAuth class. Although this class is capable of adding new user to the repository I recommend to switch in-band registration off due to the caching problems in Drupal. Changes in database are not synchronized with Drupal yet. Function for adding new users is implemented only to ease user accounts migration from different repository type from earlier Tigase server installation.
The idea of that implementation was to allow all accounts administration tasks from Drupal like: account creation, all accounts settings, like e-mail, full name, password changes and so on.
Tigase server uses following fields from Drupal database: name (user account name), pass (user account password), status (status of the account). Server picks up all changes instantly. If user status is not 1 then server won't allow user to login trough Jabber/XMPP even if user provides valid password.
There is no Roster management in Drupal yet. So Roster management have to be done from Jabber/XMPP client.
Administration manuals and guides for the Tigase server version 4.x line.
The main and actually the only configuration for the Tigase server is kept in the XML file. Let's call it tigase.xml for further discussion.
When the user tries to setup the client for the first time he comes across 2 other configuration files: tigase.conf and init.properties which might be confusing. Here is a brief explanation what all those files are about and in other sections you can learn all the details needed to configure the server.
A detailed description of all the configuration options is in the init.properties guide where you can also find information described below and much more. Purpose of this document however is to give you a quite and brief information how to load a component into the Tigase server without need to dig through all the details.
I will show how to load 2 components into the Tigase server using configuration in the init.properties file: MUC and PubSub. Please remember, every time you change something in the init.properties file you have to remove the XML configuration file in order to force the server to regenerate the main configuration which is stored in XML file.
The first thing you need is the component implementation. Component implementation is a class or set of classes extending tigase.server.AbstractMessageReceiver. What you need to do is just putting the jar file in the libs/ directory in the Tigase server installation. Then the Tigase server will find all classes automatically at the startup time.
Next step is to tell the server what components to load, how to name them and optionally give some extra parameters. To do so please open the init.properties file you use in your installation. It might be init-mysql.properties or init-pgsql.properties or even your own properties file.
Let's say you want to add just PubSub for now. All you need to do is adding just 2 lines to the properties file:
--comp-name-1=pubsub --comp-class-1=tigase.pubsub.PubSubClusterComponent
They mean: the first component name is 'pubsub' and the main class for this component is: 'tigase.pubsub.PubSubClusterComponent. It doesn't really matter what the component name is the only requirement is that it must be unique among other components names. It does also help to give it a name which means something thus 'pubsub' is a good name for a 'PubSub' component but it would be a bad name for the 'MUC' component.
We can of course add more components even PubSub components to the same server. Each of them would need to have a different name then. For example:
--comp-name-2=pubsub-priv --comp-class-2=tigase.pubsub.PubSubClusterComponent
Which is needed in really rare cases.
Normally, however we want to load few different components like PubSub, MUC, MSN Transport and so on.... Therefore instead of the above second PubSub we can load the MUC component:
--comp-name-2=muc --comp-class-2=tigase.muc.MUCService
Again! Don't forget to remove your XML config file before restarting the server.
Tigase server offers you quite a few authentication connectors which allow you to connect to almost any SQL database for user authentication data and share user accounts between the XMPP server and any different system. This feature makes it possible to integrate the Tigase server with other systems without any development effort and without any coding.
This article presents configuration options available to the administrator and describe how to set the Tigase server up to use user accounts data from a different database.
The first thing to know is that the Tigase server always opens 2 separate connections to the database. One connection is for user login data and another is for all other user data like the user roster, vCard, private data storage, privacy lists and so on...
In this article we still assume that the Tigase server keeps user data in it's own database and only login data are retrieved from the external database.
At the moment the Tigase server offers following authentication connectors:
As always the simplest way to configure the server is through the init.properties file. In the article describing this file you can find long list with all available options and all details how to handle it. For the authentication connector setup however we only need 2 options:
If you happen to keep the user data in the same database as user authentication data you can even skip the second parameter as Tigase automatically assumes settings from the '--user-db-uri' it '--auth-db-uri' is missing.
'--auth-db-uri' stored a standard JDBC connection URL and is exactly the same as for all other settings. For example if you store authentication data in the 'drupal' database on 'localhost' the URL might look like:
--auth-db-uri = jdbc:mysql://localhost/drupal?user=user&password=passwd
'--auth-db' stored just a connector name or connector implementation class. For convenience the Tigase has predefined short names for the most common connectors but you can always use the class name if you know it. And you have to use a class name if you want to attach your own authentication connector. The following 2 settings are equal:
--auth-db = tigase-auth
--auth-db = tigase.db.jdbc.TigaseAuth
In the same exact way you can setup connector for any different database type:
--auth-db = drupal
--auth-db = tigase-custom
You can normally skip configuring connectors for the default Tigase database format: 'mysql', 'pgsql' and 'derby' as they are applied automatically if the parameter is missing.
One more important thing to know is that you also have to modify '--user-db-uri' if you use a custom authentication connector. This is because if you retrieve user login data from the external database this external database is usually managed by external system. User accounts are added without notifying the Tigase server. Then, when the user logins and tries to retrieve the user roster the server can not find such a user in the roster database.
To keep user accounts in sync between authentication database and the main user database you have to add following option to the end of the database connection URL: 'autoCreateUser=true'.
For example:
--user-db-uri=jdbc:mysql://localhost/tigasedb?user=nobody&password=pass&autoCreateUser=true
If you are interested in even further customize you authentication connector by writing your own queries or stored procedures please have a look at 2 following guides: Tigase Auth guide and Tigase Custom Auth guide.
init.properties is a little bit extended version of the Java properties file with (key, value) pairs.
Comment line has it's first non-white space ASCII character either '#' or '!'.
The key starts with first non-white space ASCII character and ends on either first white space ASCII character or either of '=' or ':'. Therefore if your key contains any of '=', ':' or white space characters you have to escape them with backslash '\': \: or \=.
All of examples below specify 'vhosts' as a key and 'test-a, test-b, test-c' as a value:
vhosts=test-a, test-b, test-c
vhosts : test-a, test-b, test-c
vhosts = test-a, test-b, test-cNormally you can just copy any property from the XML file to the init.properties file and assign other than a default value which will be used the next time XML file is generated. Let's say we have following XML file section:
<component name="bosh">
<node name="5280">
<map />
<node name="tls">
<map>
<entry type="String" key="allow-invalid-certs" value="false" />
</map>
</node>
</node>
</component>To set the default value for this parameters in the init.properties file you need to assign a value to the key. The key consists of the component name, all node names and the key: 'bosh/5280/tls/allow-invalid-certs' and the value is simply 'false'. So in your init.properties file you simply put following line:
bosh/5280/tls/allow-invalid-certs = false
If you look closer in inside the XML file you can see that each parameter has a 'key', 'value' and a 'type'. If you put the parameter in the init.properties file you must specify the type of the parameter as well. Otherwise the property won't be loaded. The default type is 'String' therefore for string properties you don't have to specify the type. For all others the type must be set. The type is set by appending [T] at the end of the key name where 'T' indicates the type. Possible types are:
Let's say we want to set some timeout which is a long type property to value 60:
ssender/games-list-updater/interval[L]=60
Except the XML parameters you can inject during the configuration generation time there is a bunch of parameters which have broader meaning than just one property. Some of them affect many configuration settings or can generate whole sections in the XML file. Most of them starts with '--' - double hyphen. Here is a list of all those parameters with description:
'sm' and 'ext2s'.'c2s', 's2s', 'ext2s'.mysql, pgsql, xml or the class name. For SQL database this is normally: tigase.db.jdbc.JDBCRepository.mysql, pgsql, xml, drupal, libresource, tigase-auth and tigase-custom (If omitted 'user-db' settings are used.) or the class name. For SQL database this is normally: tigase.db.jdbc.JDBCRepository.'user-db-uri' settings are used.)'localdomain,remotedomain,port,passwd,(plain|ssl),(accept|connect),routing''--ext-comp_1 parameters', '--ext-comp_2 parameters' and so on...'domain1,domain2'. This option causes to use virtual hosts given here instead of default/automatically detected host names.'user1@domain,user2@domain2'tigase.server then you have to put parameter: '--debug server'. If you have any problems with your server the best way to get help from me is to generate configuration with '--debug = server' and run the server. Then from the logs/tigase-console.log log file I can get all information I need to give you a help. More details about server logging and adjusting logging level is described in article Debugging Tigase.'config-type' you use. Together with '--comp-class-1' it allows you to load any extra component to your server configuration. Of course you can load more than just one component. Just use '--comp-name-2', '--comp-name-3' and so on... Let's say you want to load the MUC component. You can then put give it a name: 'muc' and the setting would look like:--comp-name-1 = muc
'config-type' you use. You can, of course, load more than just one component using parameters: '--comp-class-2', '--comp-class-3' and so on.... Let's say you want to load the MUC component and the class name for the component is: 'tigase.muc.MUCService'. The line in the properties file should look like:--comp-class-1 = tigase.muc.MUCService
--cluster-nodes=host-a.domain.com,host-b.domain.com,host-c.domain.com
All cluster nodes must be connected with each other to maintain user session synchronization and exchange packets between users connected to different nodes. Therefore each cluster node opens a 'cluster port' on which it is listening for connections from different cluster nodes. As there is only one connection between each two nodes the Tigase server has to decide which nodes connects and which has to accept the connection. If you put the same list of cluster nodes in the configuration for all nodes this is not a problem. The Tigase server has a way to find it out and void conflicts. If you however want to add a new node later on, without restarting and changing configuration on old nodes there is no way the old nodes will try to establish a connection to the new node they don't know of. To solve this particular case the next parameter is used.
Property file name for tigase.sh startup script is a second parameter for the startup script. It can be skipped if environmental variables are set in different place or in different way.
Config file for startup script simply sets number of environment variables with location of required components. Possible variables to set in this file are:
JAVA_HOME - location of Java installation home directory. Must be set.TIGASE_HOME - location of Tigase installation home directory. By default script try to find this location by searching directories from the location where the script has been run.TIGASE_CONSOLE_LOG - file to which all console messages will be redirected if server is run in background. By default it will be: TIGASE_HOME/logs/tigase-console.log. If this file/directory is not writable by Tigase process all console messages will be redirected to /dev/nullTIGASE_PID location of the file with server PID number. By default it will be TIGASE_HOME/logs/tigase.pid.TIGASE_CONFIG - location of the Tigase server config file. This is main config XML file. Not to be confused with startup script parameters file. If not set script trys to find it in following locations in given order: /etc/conf.d/tigase-server.xml, /etc/tigase-server.xml, /etc/tigase/tigase-server.xml or finally in TIGASE_HOME/etc/tigase-server.xmlJAVA_OPTIONS - options for JVM like size of RAM allocated for the JVM, properties and so on.TIGASE_OPTIONS - additional options for Tigase server program. You can tweak here initial parameters for your environment.Sample file to run Tigase with PostgreSQL database may look like:
ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
DRV="-Djdbc.drivers=org.postgresql.Driver"
JAVA_OPTIONS="${ENC} ${DRV} -server -Xms100M -Xmx100M "
CLASSPATH=""
TIGASE_CONFIG="tigase-pgsql.xml"
TIGASE_OPTIONS=" --property-file etc/init.properties "Please note encoding settings. I have received several requests about encoding problems. JVM by default uses encoding set in operating system environment. XMPP protocol, however uses UTF-8 for all data processing. So the above settings enforces UTF-8 encoding for all operations.
Another significant setting is 'CLASSPATH'. It is intentionally set to empty string. The tigase.sh startup script builds the CLASSPATH on it's own from files found in jars/ and libs/ directories. I advice to set the CLASSPATH to the empty string because the Tigase server scans all available classes to find all components and plugins implementation. If the CLASSPATH contains lots of libraries which are not used anyway it cases long startup time and lots of memory consumption.
The Tigase Auth connector with shortcut name: tigase-auth is implemented in the class: tigase.db.jdbc.TigaseAuth. It allows you to connect to any external database to perform user authentication.
You can find more details how to setup a custom connector in Custom Authentication Connectors guide.
To make this connector working you have to prepare your database to offer set of stored procedures for the Tigase server to perform all the authentication actions. The best description is the example schema with all the stored procedures defined. Please refer to the Tigase SVN repository for the schema definition files.
Files with the stored procedures implementations are located in mysql-schema-4-sp.schema for MySQL database and in postgresql-schema-4-sp.schema file for PostgreSQL database. You can also refer to the tables definition files to see how database is organized in our implementation: mysql-schema-4.sql file for MySQL database and postgresql-schema-4.sql file for PostgreSQL database.
The absolute minimum of stored procedures you have to implement is:
With these 2 above stored procedures you can only perform user login/logout on the external database. You can't register a user account, change user password or remove the user. In many cases this is fine as all the user management is handled by the external system.
If you however want to allow for account management via XMPP you have to implement also following procedures:
The Tigase Custom Auth connector with shortcut name: tigase-custom is implemented in the class: tigase.db.jdbc.TigaseCustomAuth. It allows you to connect to any external database to perform user authentication and use a custom queries for all actions..
You can find more details how to setup a custom connector in Custom Authentication Connectors guide.
The basic configuration is very simple:
--auth-db = tigase-custom
--auth-db-uri = jdbc:mysql://localhost/drupal?user=user&password=passwdThat's it.
The connector loads correctly and starts working using predefined, default list of queries. In most cases you also want to define your own queries in the configuration file. The shortest possible description is the following example of the content from init.properties file:
sess-man/auth-repo-params/conn-valid-query=select 1
sess-man/auth-repo-params/init-db-query=update tig_users set online_status = 0
sess-man/auth-repo-params/add-user-query={ call TigAddUserPlainPw(?, ?) }
sess-man/auth-repo-params/del-user-query={ call TigRemoveUser(?) }
sess-man/auth-repo-params/get-password-query=select user_pw from tig_users where user_id = ?
sess-man/auth-repo-params/update-password-query=update tig_users set user_pw = ? where user_id = ?
sess-man/auth-repo-params/user-logout-query=update tig_users, set online_status = online_status - 1 where user_id = ?
sess-man/auth-repo-params/non-sasl-mechs=password,digest
sess-man/auth-repo-params/sasl-mechs=PLAIN,DIGEST-MD5Queries are defined in the configuration file and they can be either plain SQL queries or stored procedures. If the query starts with characters: '{ call' then the server assumes this is a stored procedure call, otherwise it is executed as a plain SQL query. Each configuration value is stripped from white characters on both ends before processing.
Please don't use semicolon ';' at the end of the query as many JDBC drivers get confused and the query may not work for unknown reason.
Some queries take arguments. Arguments are marked by question marks '?' in the query. Refer to the configuration parameters description for more details about what parameters are expected in each query.
The first example shows how to put a stored procedure as a query with 2 required parameters.
add-user-query={ call TigAddUserPlainPw(?, ?) }The same query with plain SQL parameters instead:
add-user-query=insert into users (user_id, password) values (?, ?)
The order of the query arguments is important and must be exactly as described in specification for each parameter.
Takes no arguments.
Example query: 'select 1'
Takes no arguments.
Example query: 'update tig_users set online_status = 0'
Takes 2 arguments: (user_id (JID), password)
Example query: 'insert into tig_users (user_id, user_pw) values (?, ?)'
Takes 1 argument: (user_id (JID))
Example query: 'delete from tig_users where user_id = ?'
Takes 1 argument: (user_id (JID))
Example query: 'select user_pw from tig_users where user_id = ?'
Takes 2 arguments: (password, user_id (JID))
Example query: 'update tig_users set user_pw = ? where user_id = ?'
user-login-query or get-password-query.
If both queries are defined then user-login-query is used. Normally this method should be only used with plain text password authentication or sasl-plain.
The Tigase server expects a result set with user_id to be returned from the query if login is successful and empty results set if the login is unsuccessful.
Takes 2 arguments: (user_id (JID), password)
Example query: 'select user_id from tig_users where (user_id = ?) AND (user_pw = ?)'
Takes 1 argument: (user_id (JID))
Example query: 'update tig_users, set online_status = online_status - 1 where user_id = ?'
password and digest. digest mechanism can work only with get-password-query active and only when password are stored in plain text format in the database.PLAIN, DIGEST-MD5, CRAM-MD5.get-password-query active and only when passwords are stored in plain text formay in the database.
For number of reasons the database schema had to be changed for Tigase server version 4.0. The most important are:
Therefore when you run the Tigase server now it may (depending on what exact SVN revision you use) refuse to start if it detects that the database schema is not updated. If it happens just follow steps below to update the database schema and start the server again. Updating of the database schema is very easy and almost fully automated process. Just follow the steps below and you should be able to run new version of the Tigase server in a few minutes or even seconds depending on your database size. It takes around 7 minutes to update database with 200k user accounts on an average machine. Note. Do not update the database schema before the Tigase server tells you to do so. And do a database backup before starting the schema update.
Please note. I have done a few schema upgrades already in a different configurations and here are a few tips which might be useful if something goes wrong:
$ mysql -u root -proot_passwd mysql
mysql> GRANT SELECT, INSERT, UPDATE ON \`mysql\`.\`proc\` TO 'tigase_user'@'localhost';
mysql> GRANT SELECT, INSERT, UPDATE ON \`mysql\`.\`proc\` TO 'tigase_user'@'%';
mysql> GRANT SELECT, INSERT, UPDATE ON \`mysql\`.\`proc\` TO 'tigase_user';
mysql> FLUSH PRIVILEGES;
$
First things first - make a database backup:
mysqldump -u tigase_user -pmypass tigasedb > tigasedb_dump.sql
If you need to restore database for any reason execute following commands:
msyqladmin -u tigase_user -pmypass drop tigasedb mysqladmin -u tigase_user -pmypass create tigasedb mysql -u tigase_user -pmypass tigasedb < tigasedb_dump.sql
Note! You may be required to use root user and his password to execute mysqladmin commands. Ok we have the database backup and we know how to restore it. Now we can run schema upgrade script:
mysql -u tigase_user -pmypass tigasedb < database/mysql-schema-upgrade-to-4.sql
The script should generate output like this:
Droping index for user_id column Resizing user_id column to 2049 characters to comply with RFC Creating a new index for user_id column for first 765 bytes of the field Adding sha1_user_id column Adding user_pw column Adding last_login column Adding last_logout column Adding online_status column Adding failed_logins column Adding account_status column Creating a new index for user_pw column Creating a new index for last_login column Creating a new index for last_logout column Creating a new index for account_status column Creating a new index for online_status column Resizing node column to 255 characters Changing pval column type to mediumtext Loading stored procedures definitions Setting passwords encoding in the database Converting database to a new format Creating a new index for sha1_user_id column Setting schema version to 4.0 All done, database ready to use!
Let's assume you have a cluster installation and you want to include a component in your installation which doesn't support the cluster mode yet. If you put it on all nodes as a separate instances they will work out of sync and overall functionality might be useless. If you put on one node only it will work correctly but it will be visible to users connected to this one node only.
Ideally you would like to have a mechanism to install it on one node and put some redirections on other nodes to forward all packets for this component to a node where this component is working. Redirection on it's own is not enough however because the component must be visible in service discovery list and must be visible somehow to users connected to all nodes.
This is where the virtual components are handy. They are visible to users as a local normal component, they seem to be a real local component but in fact they just forward all requests/packets to a cluster node where the real component is working.
Virtual component is a very lightweight ServerComponent implementation in the Tigase server. It can pretend to be any kind of component and can redirect all packets to a given address. They can mimic native Tigase components as well as third-party components connected over external component protocol (XEP-0114).
Configuration is very simple and straightforward. In fact it is very similar to configuration of any Tigase component. You set a real component name as a name of the component and a vritual component class name to load. Let's say we want to deploy MUC component this way. The MUC component is visible as muc.domain.our in the installation. Thus the name of the component is: muc
--comp-name-1=muc --comp-class-1=tigase.cluster.VirtualComponent
This is pretty much all you need to load a virtual component. A few other options are needed to point to correct destination addresses for packets forwarding and to set correct service discovery parameters:
muc/redirect-to=muc@cluster-node-with-real-muc.domain.our muc/disco-name=Multi User Chat muc/disco-node= muc/disco-type=text muc/disco-category=conference muc/disco-features=http://jabber.org/protocol/muc
That's it.
The Tigase server supports multiple virtual hosts for a single server installation. This is supported via VHostManager - the new Tigase server component added recently to the implementation. Virtual hosts can be added or removed, enabled or disabled at the server runtime without restarting the service or disrupting normal operation.
This document describes how virtual hosts work in the Tigase server and how to take the most of this feature in your installation.
The simplest and default way to set virtual hosts is the server configuration. You can either edit manually the init.properties file or use the graphical installer/configuration program to set the property. If you want to edit it manually search for '--virt-hosts' property for more detailed description.
Alternatively you can use the GUI installer as shown on the left hand side to set a list of virtual hosts.
This method however has many disadvantages. It requires the server restart after each change, the configuration file is not the best place to store long list of virtual domains and you can not actually set any additional parameters for the domain other than it does exist or not.
There is another way to store and control virtual domains in the Tigase server. They can be put in the database and managed using ad-hoc commands. List of domains can be modified outside the Tigase server through any third-party system or web application and the server reloads the list of when received VHOSTS_RELOAD ad-hoc command.
There are 2 more ad-hoc commands which allow you to add/update and remove virtual hosts via XMPP protocol:
By default, both commands cause vhosts list update in the permanent repository. This is however VHostRepository implementation dependent feature and can be changed in your repository implementation.
Commands for virtual domains management can be executed using any XMPP client with a good support for service discovery and ad-hoc commands, for example Psi. Commands are accepted only when they are sent by the service administrator.
Please refer to documents listed below for more detailed information on the following topics:
There are 3 ad-hoc commands for virtual domains management in the Tigase server:
Syntax of the commands follows specification described in the XEP-0050. Extra information required to complete the command is carried as data forms described in the XEP-0004.
All commands are accepted by the server only when send by the installation administrator. If the command is sent from any other account <not-authorized /> error is returned. To grant administrator rights to an account you have to set --admins property in the configuration file.
Commands are sent to 'vhost-man' server component and the 'to' attribute of the stanza must contain a full JID of the VHostManager on the server. The full JID consists of the component name: 'vhost-man' and the local domain, that is domain which is already on the list of virtual domains and is active. Assuming 'existing.domain.com' one of domains already activated for the server installation the JID is: 'vhost-man@existing.domain.com'.
In order to reload virtual domains from the permanent repository other than configuration file you have to send VHOSTS_RELOAD ad-hoc command to the VHostManager on the server.
The reload command request is of the form:
<iq type="set"
to="vhost-man@existing.domain.com"
id="aac8a">
<command xmlns="http://jabber.org/protocol/commands"
node="VHOSTS_RELOAD" />
</iq>The server sends a response upon successful completion of the command with current number of virtual domains server by the installation:
<iq from="vhost-man@existing.domain.com"
type="result"
to="cmd-sender-admin@existing.domain.com"
id="aac8a">
<command xmlns="http://jabber.org/protocol/commands"
status="completed"
node="VHOSTS_RELOAD">
<x xmlns="jabber:x:data" type="result">
<field type="fixed" var="Note">
<value>Current number of VHosts: 123</value>
</field>
</x>
</command>
</iq>If the command is sent from other than admin account the server returns an error:
<iq from="vhost-man@existing.domain.com"
type="error"
to="cmd-sender-admin@existing.domain.com"
id="aac8a">
<command xmlns="http://jabber.org/protocol/commands"
node="VHOSTS_RELOAD" />
<error type="auth" code="401">
<not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"
xml:lang="en">
You are not authorized for this action.
</text>
</error>
</iq>The response doesn't have any special meaning other then informative for the end-user. The client may ignore response as it is sent after the command has been executed.
In order to add a new domain or update existing one you have to send an ad-hoc command VHOSTS_UPDATE with at least domain name in the command data form. You can also specify whether the domain is enabled or disabled but this is optional. Future releases may allow for setting additional parameters for the domain: maximum number of user accounts for this domain, anonymous login enabled/disabled for the domain, registration via XMPP enabled/disabled for this domain and some more parameters not specified yet.
The domain add/update command request is of the form:
<iq type="set"
to="vhost-man@existing.domain.com"
id="aacba">
<command xmlns="http://jabber.org/protocol/commands"
node="VHOSTS_UPDATE">
<x xmlns="jabber:x:data" type="submit">
<field type="text-single"
var="VHost">
<value>new-virt.domain.com</value>
</field>
<field type="list-single"
var="Enabled">
<value>true</value>
</field>
</x>
</command>
</iq>Please note! Character case in the command field variable names does matter.
Upon successful completion of the command the server sends a response back to the client with information of the existing number of virtual hosts on the server:
<iq from="vhost-man@existing.domain.com"
type="result"
to="cmd-sender-admin@existing.domain.com"
id="aacba">
<command xmlns="http://jabber.org/protocol/commands"
status="completed"
node="VHOSTS_UPDATE">
<x xmlns="jabber:x:data" type="result">
<field type="fixed" var="Note">
<value>Current number of VHosts: 124</value>
</field>
</x>
</command>
</iq>
In order to remove a virtual domain you have to send VHOSTS_REMOVE command to the server with the domain name.
The domain remove command is sent by the client:
<iq type="set"
to="vhost-man@existing.domain.com"
id="aacba">
<command xmlns="http://jabber.org/protocol/commands"
node="VHOSTS_REMOVE">
<x xmlns="jabber:x:data" type="submit">
<field type="text-single"
var="VHost">
<value>virt-nn.domain.com</value>
</field>
</x>
</command>
</iq>Upon successful completion of the command the server sends a response back to the client with information of the existing number of virtual hosts on the server:
<iq from="vhost-man@existing.domain.com"
type="result"
to="cmd-sender-admin@existing.domain.com"
id="aacba">
<command xmlns="http://jabber.org/protocol/commands"
status="completed"
node="VHOSTS_REMOVE">
<x xmlns="jabber:x:data" type="result">
<field type="fixed" var="Note">
<value>Current number of VHosts: 124</value>
</field>
</x>
</command>
</iq>
Admin manuals and guides for the Tigase server version 3.x line.
This section contains the Tigase server configuration manuals and guides.
From the build #247 you can use configuration generators to easily and quickly create configuration file for even complex case.
Tigase configuration is not too easy to understand and maintain. Even with current command line tools you still have to know what the all options are for.
To make it easier for average administrators or people who run the server for the first time or even for those who want to quickly test Tigase server in different scenarios configuration generators have been created. For each generator you can have also a few extra options which allows you to create configuration which you don't need to change for some time.
A few definitions first to make it easier to read the rest:
The are 4 generators currently available:
--gen-config-all - creating configuration file with all available components. That is: sm, c2s, s2s, ext2s, ssender.--gen-config-default - creating default configuration file. That is configuration which is most likely needed for basic installation. Components included in configuration are: sm, c2s, s2s.--gen-config-sm - creating configuration for instance with session manager and external component only. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: sm and ext2s.--gen-config-cs - creating configuration for instance with components managing network connections. This is useful for distributed installation where you want to have session manager installed on separate machine and components managing network connections on different machines (one or more). Components included in configuration are: c2s, s2s, ext2s.