diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 7fda9c42..01161a5f 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ 7.4, 8.0 ] + php: [ 7.4, 8.0, 8.2 ] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index ff36e7e5..e44b0838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 20260624 +## What's Changed +* master office: prepare doil to deploy an OnlyOffice run-document-server +* add 2 apply states to en/disable office support for a specific ilias instance + ## 20260611 ## What's Changed * update_hook.php - ensure that ilias >= 10 always has the update_hook file in public folder; works for CaT and Essential @@ -31,6 +36,33 @@ * use node/npm versions depending on ilias version * use new salt.sources while creating/importing instances +## 20260323 +## What's Changed +* master ilias-update-hook: adjust COMPOSER_HOME to point at correct location by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/562 +* master add update file for release 20260323 by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/563 + +## 20260319 +## What's Changed +* master 555: enable ILIAS https depending on doil https_proxy property by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/558 + +## 20260318 +## What's Changed +* master ilias cron: add path to cron starting script depending on ilias version by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/557 + +## 20260224 +## What's Changed +* master quick_fix: fix last release by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/552 + +## 20260223 +## What's Changed +* master SetIdpV10: new initialisation routine by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/551 + +## 20251125 +## What's Changed +* Master hotfix 20251125 by @daniwe4 in https://github.com/conceptsandtraining/doil/pull/543 +* use node/npm versions depending on ilias version +* use new salt.sources while creating/importing instances + ## 20251103 ## What's Changed * update Captainhook Hooks while running update_hook script diff --git a/README.md b/README.md index 2504103b..c010ef0f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ all mails from your instances, so you can test the ILIAS emailing. 1. adjust your mail password in `setup/conf/doil.conf` 1. if you run global instances make sure to adjust 'global_instances_path' in `setup/conf/doil.conf` to specify where to place them, default is '/srv/instances'. Attention, paths with 'home' are not allowed here. +1. if you want to enable office support ensure to set enable_office to true in `setup/conf/doil.conf` 1. execute `sudo ./setup/install.sh` in order to install **doil** 1. you can remove the downloaded folder afterwards 1. check `doil help` for available commands and further instructions @@ -56,7 +57,7 @@ however **doil** needs [Docker](https://www.docker.com/) in order to work: * git * .ssh folder in your home directory. **doil** will mount it into the container. **doil** needs this to have access to any private git repositories that may be used. -Additional dependencies, but these are installed automatically during setup. +Additional dependencies, but these are installed automatically during setup and only inside containers. * php version => 7.4 * php*.*-zip @@ -72,6 +73,12 @@ Additional dependencies, but these are installed automatically during setup. * psr/log * monolog/monolog +if office is enabled, these dependencies will also be installed + +* onlyoffice/documentserver +* postgres +* rabbitmq + The easiest way to fulfill the dependencies is Ubuntu 22.01, but it should also be possible with any other Linux installation. ## Usage @@ -436,6 +443,26 @@ users, so make sure to understand what you are doing. See `doil keycloak: --help` for more information + +### Office Sever + +If enabled **doil** installs an OnlyOffice server. This enables ILIAS to +support document editing in office style. + +* `doil office:down` stops the office server +* `doil office:login` logs the user into the office server +* `doil office:restart` restarts the office server +* `doil office:up` starts the office server + +See `doil office: --help` for more information + +To enable or disable Office support for a specific ILIAS instance, there +are two states that can be selected using `doil apply `. +These are `enable-office` and `disable-office`. + +When a new instance is installed, you are asked during the installation +process whether Office should be activated for this instance. + ### xdedug **doil** provides two options to enable xdebug for the given instance. diff --git a/app/src/App.php b/app/src/App.php index fe75a092..0986237b 100644 --- a/app/src/App.php +++ b/app/src/App.php @@ -9,7 +9,7 @@ class App extends Application { - const NAME = "Doil Version 20260617 - build 2026-06-17"; + const NAME = "Doil Version 20260624 - build 2026-06-24"; public function __construct(Command ...$commands) { diff --git a/app/src/Commands/Instances/CreateCommand.php b/app/src/Commands/Instances/CreateCommand.php index efe9f144..376155ff 100644 --- a/app/src/Commands/Instances/CreateCommand.php +++ b/app/src/Commands/Instances/CreateCommand.php @@ -100,13 +100,14 @@ public function configure() : void ->addOption("xdebug", "x", InputOption::VALUE_NONE, "Determines if xdebug should be installed or not") ->addOption("global", "g", InputOption::VALUE_NONE, "Determines if an instance is global or not") ->addOption("skip-readme", "s", InputOption::VALUE_NONE, "Doesn't create the README.md file") + ->addOption("enable-office", "o", InputOption::VALUE_NONE, "Enable office support") ; } public function execute(InputInterface $input, OutputInterface $output) : int { - $options = $this->gatherOptionData($input, $output); $doil_conf = $this->filesystem->parseIniFile(self::DOIL_INI_PATH); + $options = $this->gatherOptionData($input, $output, $doil_conf); $host = $doil_conf["host"]; $allowed_hosts = $doil_conf["allowed_hosts"]; @@ -492,6 +493,13 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->writer->endBlock(); } + if ($options['enable_office']) { + // apply enable-office state + $this->writer->beginBlock($output, "Apply enable-office state"); + $this->docker->applyState($instance_salt_name, "enable-office"); + $this->writer->endBlock(); + } + // apply access state $this->writer->beginBlock($output, "Apply access state"); $this->docker->applyState($instance_salt_name, "access"); @@ -574,7 +582,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int return Command::SUCCESS; } - protected function gatherOptionData(InputInterface $input, OutputInterface $output) : array + protected function gatherOptionData(InputInterface $input, OutputInterface $output, array $doil_conf) : array { $options = []; @@ -587,6 +595,7 @@ protected function gatherOptionData(InputInterface $input, OutputInterface $outp $xdebug = $input->getOption("xdebug"); $global = $input->getOption("global"); $skip_readme = $input->getOption("skip-readme"); + $enable_office = $input->getOption("enable-office"); $one_option_missed = is_null($name) || is_null($repo) || is_null($branch) || is_null($php_version) || is_null($target); @@ -738,6 +747,17 @@ protected function gatherOptionData(InputInterface $input, OutputInterface $outp } $options["skip_readme"] = $skip_readme; + // Enable office support + if (!$enable_office && $one_option_missed && $doil_conf['enable_office']) { + $question = new ConfirmationQuestion( + "Enable office support? [yN]: ", + false + ); + $enable_office = $helper->ask($input, $output, $question); + } + $options["enable_office"] = $enable_office; + + // Target if (is_null($target) && !$global) { $question = new Question("Please enter a target where doil should install " . $options["name"] . ". Leave blank for current directory. : "); diff --git a/app/src/Commands/Instances/StatusCommand.php b/app/src/Commands/Instances/StatusCommand.php index 62bffb48..d500b004 100644 --- a/app/src/Commands/Instances/StatusCommand.php +++ b/app/src/Commands/Instances/StatusCommand.php @@ -38,6 +38,9 @@ public function execute(InputInterface $input, OutputInterface $output) : int strstr($a, "doil_proxy") || strstr($a, "doil_saltmain") || strstr($a, "doil_keycloak") || + strstr($a, "doil_office") || + strstr($a, "doil_postgresql") || + strstr($a, "doil_rabbitmq") || strstr($a, "_local") || strstr($a, "_global") ) { diff --git a/app/src/Commands/Office/DownCommand.php b/app/src/Commands/Office/DownCommand.php new file mode 100644 index 00000000..63936137 --- /dev/null +++ b/app/src/Commands/Office/DownCommand.php @@ -0,0 +1,45 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\Office; + +use CaT\Doil\Lib\Docker\Docker; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class DownCommand extends Command +{ + protected const OFFICE_PATH = "/usr/local/lib/doil/server/office"; + + protected static $defaultName = "office:down"; + protected static $defaultDescription = "Stops the office server"; + + protected Docker $docker; + protected Writer $writer; + + public function __construct(Docker $docker, Writer $writer) + { + parent::__construct(); + + $this->docker = $docker; + $this->writer = $writer; + } + + + public function execute(InputInterface $input, OutputInterface $output) : int + { + if (! $this->docker->isInstanceUp(self::OFFICE_PATH)) { + $output->writeln("Nothing to do. Office is already down."); + return Command::SUCCESS; + } + + $this->writer->beginBlock($output, "Stop office"); + $this->docker->stopContainerByDockerCompose(self::OFFICE_PATH); + $this->writer->endBlock(); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/app/src/Commands/Office/LoginCommand.php b/app/src/Commands/Office/LoginCommand.php new file mode 100644 index 00000000..825e0758 --- /dev/null +++ b/app/src/Commands/Office/LoginCommand.php @@ -0,0 +1,38 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\Office; + +use CaT\Doil\Lib\Docker\Docker; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class LoginCommand extends Command +{ + protected const OFFICE_PATH = "/usr/local/lib/doil/server/office"; + + protected static $defaultName = "office:login"; + protected static $defaultDescription = "Login into the office server"; + + protected Docker $docker; + + public function __construct(Docker $docker) + { + parent::__construct(); + + $this->docker = $docker; + } + + + public function execute(InputInterface $input, OutputInterface $output) : int + { + if (! $this->docker->isInstanceUp(self::OFFICE_PATH)) { + $this->docker->startContainerByDockerCompose(self::OFFICE_PATH); + } + + $this->docker->loginIntoContainer(self::OFFICE_PATH, "doil_office"); + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/app/src/Commands/Office/RestartCommand.php b/app/src/Commands/Office/RestartCommand.php new file mode 100644 index 00000000..80c15528 --- /dev/null +++ b/app/src/Commands/Office/RestartCommand.php @@ -0,0 +1,66 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\Office; + +use CaT\Doil\Lib\Docker\Docker; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class RestartCommand extends Command +{ + protected const OFFICE_PATH = "/usr/local/lib/doil/server/office"; + + protected static $defaultName = "office:restart"; + protected static $defaultDescription = "Restarts the office server"; + + protected Docker $docker; + protected Writer $writer; + + public function __construct(Docker $docker, Writer $writer) + { + parent::__construct(); + + $this->docker = $docker; + $this->writer = $writer; + } + + + public function execute(InputInterface $input, OutputInterface $output) : int + { + if (! $this->docker->isInstanceUp(self::OFFICE_PATH)) { + $this->docker->startContainerByDockerCompose(self::OFFICE_PATH); + return Command::SUCCESS; + } + + $this->writer->beginBlock($output, "Restart office"); + $this->docker->stopContainerByDockerCompose(self::OFFICE_PATH); + $this->docker->startContainerByDockerCompose(self::OFFICE_PATH); + sleep(3); + $instances = array_filter($this->docker->getRunningInstanceNames()); + foreach ($instances as $instance) { + if ($instance == "doil_office") { + continue; + } + if ( + strpos($instance, 'doil_') != false || + strpos($instance, '_local') != false || + strpos($instance, '_global') != false + ) { + try { + $this->docker->executeDockerCommand( + $instance, + "supervisorctl start startup 2>&1 >/dev/null" + ); + } catch (\Exception $e) { + } + } + } + $this->writer->endBlock(); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/app/src/Commands/Office/UpCommand.php b/app/src/Commands/Office/UpCommand.php new file mode 100644 index 00000000..735f77ac --- /dev/null +++ b/app/src/Commands/Office/UpCommand.php @@ -0,0 +1,63 @@ + - Extended GPL, see LICENSE */ + +namespace CaT\Doil\Commands\Office; + +use CaT\Doil\Lib\Docker\Docker; +use CaT\Doil\Lib\ConsoleOutput\Writer; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class UpCommand extends Command +{ + protected const OFFICE_PATH = "/usr/local/lib/doil/server/office"; + + protected static $defaultName = "office:up"; + protected static $defaultDescription = "Starts the office server"; + + protected Docker $docker; + protected Writer $writer; + + public function __construct(Docker $docker, Writer $writer) + { + parent::__construct(); + + $this->docker = $docker; + $this->writer = $writer; + } + + + public function execute(InputInterface $input, OutputInterface $output) : int + { + if ($this->docker->isInstanceUp(self::OFFICE_PATH)) { + $output->writeln("Nothing to do. Office is already up."); + return Command::SUCCESS; + } + + $this->writer->beginBlock($output, "Start office"); + + $this->docker->startContainerByDockerCompose(self::OFFICE_PATH); + sleep(3); + $instances = array_filter($this->docker->getRunningInstanceNames()); + foreach ($instances as $instance) { + if ($instance == "doil_office") { + continue; + } + if ( + strpos($instance, 'doil_') != false || + strpos($instance, '_local') != false || + strpos($instance, '_global') != false + ) { + $this->docker->executeDockerCommand( + $instance, + "supervisorctl start startup" + ); + } + } + $this->writer->endBlock(); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/app/src/Commands/Pack/ExportCommand.php b/app/src/Commands/Pack/ExportCommand.php index 3d327a99..4a57851a 100644 --- a/app/src/Commands/Pack/ExportCommand.php +++ b/app/src/Commands/Pack/ExportCommand.php @@ -24,6 +24,9 @@ class ExportCommand extends Command { + + protected const DOIL_INI_PATH = "/etc/doil/doil.conf"; + protected static $defaultName = "pack:export"; protected static $defaultDescription = "Exports an instance to an archive with all the data needed for an import." @@ -71,6 +74,7 @@ public function configure() : void public function execute(InputInterface $input, OutputInterface $output) : int { + $doil_conf = $this->filesystem->parseIniFile(self::DOIL_INI_PATH); $instance = $input->getArgument("instance"); $name = $instance . "-doilpack"; $starting = false; @@ -104,6 +108,13 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->writer->endBlock(); } + $wopi_enabled = $this->ilias_info->isWopiEnabled($instance . "_" . $suffix); + if ($this->ilias_info->getIliasVersion($path) >= 10 && $doil_conf["enable_office"] && $wopi_enabled) { + $this->writer->beginBlock($output, "Apply disable-office state"); + $this->docker->applyState($instance . "." . $suffix, "disable-office"); + $this->writer->endBlock(); + } + $this->writer->beginBlock($output, "Building zip file for " . $instance . "_" . $suffix); $this->writer->beginBlock($output, "Exporting database"); @@ -174,6 +185,12 @@ public function execute(InputInterface $input, OutputInterface $output) : int ); $this->writer->endBlock(); + if ($wopi_enabled) { + $this->writer->beginBlock($output, "Apply enable-office state"); + $this->docker->applyState($instance . "." . $suffix, "enable-office"); + $this->writer->endBlock(); + } + if ($starting) { $this->writer->beginBlock($output, "Stopping instance $instance"); $this->docker->stopContainerByDockerCompose($path); @@ -234,6 +251,7 @@ protected function exportProjectConfig(OutputInterface $output, string $path, st $cmd = "php -v | head -n 1 | cut -d ' ' -f2 | cut -d . -f1,2"; $php_version = trim($this->docker->executeDockerCommandWithReturn($instance, $cmd)); + $ilias_version = $this->ilias_info->getIliasVersion($path); $remotes = $this->git->getRemotes($path . "/volumes/ilias"); @@ -324,6 +342,7 @@ protected function exportProjectConfig(OutputInterface $output, string $path, st ->withPhpVersion($php_version) ->withRepositoryName($repo->getName()) ->withRepositoryUrl($repo->getUrl()) + ->withIliasVersion($ilias_version) ; $this->filesystem->saveToJsonFile($target_path, [$project_config]); diff --git a/app/src/Commands/Pack/ImportCommand.php b/app/src/Commands/Pack/ImportCommand.php index 33ebb81d..627cbb10 100644 --- a/app/src/Commands/Pack/ImportCommand.php +++ b/app/src/Commands/Pack/ImportCommand.php @@ -116,6 +116,16 @@ public function execute(InputInterface $input, OutputInterface $output) : int $unpacked = $dir . DIRECTORY_SEPARATOR . $target; $delete_path = $unpacked; + // Enable office support? + $enable_office = false; + if ($this->filesystem->exists($unpacked . "/conf/project_config.json")) { + $project_config = $this->filesystem->readFromJsonFile($unpacked . "/conf/project_config.json"); + $project_config = array_shift($project_config); + if ((float)$project_config->getIliasVersion() >= 10.0 && $doil_conf["enable_office"]) { + $enable_office = $this->confirmEnableOfficeSuport($input, $output, $instance); + } + } + if ($create) { // This is very ugly, but necessary for importing old doil export zips. $sql_dump = ""; @@ -323,7 +333,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $instance, "bash", "-c", - "php /var/www/html/setup/setup.php update /var/ilias/data/ilias-config.json -y" + "cd /var/www/html && php setup/setup.php update /var/ilias/data/ilias-config.json -y" ); } else if ($path . "/volumes/ilias/cli/setup.php") { $this->docker->executeCommand( @@ -331,7 +341,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int $instance, "bash", "-c", - "php /var/www/html/cli/setup.php update /var/ilias/data/ilias-config.json -y" + "cd /var/www/html && php cli/setup.php update /var/ilias/data/ilias-config.json -y" ); } else { throw new RuntimeException("Can not found setup.php."); @@ -363,6 +373,13 @@ public function execute(InputInterface $input, OutputInterface $output) : int $this->writer->endBlock(); } + if ($enable_office) { + // apply enable-office state + $this->writer->beginBlock($output, "Apply enable-office state"); + $this->docker->applyState($instance . "." . $suffix, "enable-office"); + $this->writer->endBlock(); + } + if ($https_proxy) { // apply enable-https state $this->writer->beginBlock($output, "Apply enable-https state"); @@ -428,6 +445,14 @@ protected function checkPackage() : Closure }; } + protected function confirmEnableOfficeSuport(InputInterface $input, OutputInterface $output, string $instance) : bool + { + $helper = $this->getHelper("question"); + $question = new ConfirmationQuestion("Enable office support for $instance? [yN]: ", false); + + return $helper->ask($input, $output, $question); + } + protected function confirmCreateNewInstance(InputInterface $input, OutputInterface $output, string $instance) : bool { $helper = $this->getHelper("question"); diff --git a/app/src/Commands/Pack/PackCreateCommand.php b/app/src/Commands/Pack/PackCreateCommand.php index 980eafd2..f3839656 100644 --- a/app/src/Commands/Pack/PackCreateCommand.php +++ b/app/src/Commands/Pack/PackCreateCommand.php @@ -106,8 +106,8 @@ public function configure() : void public function execute(InputInterface $input, OutputInterface $output) : int { - $options = $this->gatherOptionData($input, $output); $doil_conf = $this->filesystem->parseIniFile(self::DOIL_INI_PATH); + $options = $this->gatherOptionData($input, $output, $doil_conf); $host = $doil_conf["host"]; $allowed_hosts = $doil_conf["allowed_hosts"]; diff --git a/app/src/Lib/ILIAS/IliasInfo.php b/app/src/Lib/ILIAS/IliasInfo.php index 24ebbe57..2e6f6310 100644 --- a/app/src/Lib/ILIAS/IliasInfo.php +++ b/app/src/Lib/ILIAS/IliasInfo.php @@ -5,16 +5,20 @@ namespace CaT\Doil\Lib\ILIAS; use RuntimeException; +use CaT\Doil\Lib\Docker\Docker; use CaT\Doil\Lib\FileSystem\Filesystem; class IliasInfo implements ILIAS { protected Filesystem $filesystem; + protected Docker $docker; public function __construct( - Filesystem $filesystem + Filesystem $filesystem, + Docker $docker ) { $this->filesystem = $filesystem; + $this->docker = $docker; } public function getIliasVersion(string $path) : string @@ -36,4 +40,12 @@ public function getIliasVersion(string $path) : string return $version[0]; } + + public function isWopiEnabled(string $salt_instance_name) : bool + { + return (bool)$this->docker->executeDockerCommandWithReturn( + $salt_instance_name, + "mysql -N -B -e \"select value from ilias.settings where keyword = 'wopi_activated'\"" + ); + } } \ No newline at end of file diff --git a/app/src/Lib/ProjectConfig.php b/app/src/Lib/ProjectConfig.php index 8e04e256..51c4fdb0 100644 --- a/app/src/Lib/ProjectConfig.php +++ b/app/src/Lib/ProjectConfig.php @@ -11,19 +11,22 @@ class ProjectConfig protected string $repository_branch; protected string $repository_url; protected string $php_version; + protected string $ilias_version; public function __construct( string $name = "", string $repository_name = "", string $repository_branch = "", string $repository_url = "", - string $php_version = "" + string $php_version = "", + string $ilias_version = "" ) { $this->name = $name; $this->repository_name = $repository_name; $this->repository_branch = $repository_branch; $this->repository_url = $repository_url; $this->php_version = $php_version; + $this->ilias_version = $ilias_version; } public function getName() : string @@ -85,4 +88,16 @@ public function withPhpVersion(string $php_version) : ProjectConfig $clone->php_version = $php_version; return $clone; } + + public function getIliasVersion() : string + { + return $this->ilias_version; + } + + public function withIliasVersion(string $ilias_version) : ProjectConfig + { + $clone = clone $this; + $clone->ilias_version = $ilias_version; + return $clone; + } } \ No newline at end of file diff --git a/app/src/cli.php b/app/src/cli.php index ec46bd05..de905958 100644 --- a/app/src/cli.php +++ b/app/src/cli.php @@ -10,6 +10,7 @@ use CaT\Doil\Commands\Salt; use CaT\Doil\Commands\User; use CaT\Doil\Commands\Proxy; +use CaT\Doil\Commands\Office; use CaT\Doil\Lib\Git\GitShell; use CaT\Doil\Lib\ProjectConfig; use CaT\Doil\Commands\Keycloak; @@ -57,6 +58,10 @@ function buildContainerForApp() : Container $c["command.mail.login"], $c["command.mail.restart"], $c["command.mail.up"], + $c["command.office.down"], + $c["command.office.login"], + $c["command.office.restart"], + $c["command.office.up"], $c["command.pack.export"], $c["command.pack.import"], $c["command.pack.create"], @@ -96,7 +101,8 @@ function buildContainerForApp() : Container $c["ilias.info"] = function($c) { return new IliasInfo( - $c["filesystem.shell"] + $c["filesystem.shell"], + $c["docker.shell"] ); }; @@ -331,6 +337,33 @@ function buildContainerForApp() : Container ); }; + $c["command.office.down"] = function($c) { + return new Office\DownCommand( + $c["docker.shell"], + $c["command.writer"] + ); + }; + + $c["command.office.login"] = function($c) { + return new Office\LoginCommand( + $c["docker.shell"] + ); + }; + + $c["command.office.restart"] = function($c) { + return new Office\RestartCommand( + $c["docker.shell"], + $c["command.writer"] + ); + }; + + $c["command.office.up"] = function($c) { + return new Office\UpCommand( + $c["docker.shell"], + $c["command.writer"] + ); + }; + $c["command.pack.export"] = function($c) { return new Pack\ExportCommand( $c["docker.shell"], diff --git a/app/tests/Lib/ProjectConfigTest.php b/app/tests/Lib/ProjectConfigTest.php index 0f2d8f2b..2efdd8e5 100644 --- a/app/tests/Lib/ProjectConfigTest.php +++ b/app/tests/Lib/ProjectConfigTest.php @@ -17,6 +17,7 @@ public function test_create() : void $this->assertEmpty($project_config->getRepositoryBranch()); $this->assertEmpty($project_config->getRepositoryUrl()); $this->assertEmpty($project_config->getPhpVersion()); + $this->assertEmpty($project_config->getIliasVersion()); } public function test_create_with_params() : void @@ -26,7 +27,8 @@ public function test_create_with_params() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $this->assertEquals("name", $project_config->getName()); @@ -34,6 +36,7 @@ public function test_create_with_params() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); } public function test_withName() : void @@ -43,7 +46,8 @@ public function test_withName() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $new = $project_config->withName("test"); @@ -53,12 +57,14 @@ public function test_withName() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); $this->assertEquals("test", $new->getName()); $this->assertEquals("repo_name", $new->getRepositoryName()); $this->assertEquals("repo_branch", $new->getRepositoryBranch()); $this->assertEquals("repo_url", $new->getRepositoryUrl()); $this->assertEquals("php_version", $new->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); } public function test_withRepositoryName() : void @@ -68,7 +74,8 @@ public function test_withRepositoryName() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $new = $project_config->withRepositoryName("test"); @@ -78,12 +85,14 @@ public function test_withRepositoryName() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); $this->assertEquals("name", $new->getName()); $this->assertEquals("test", $new->getRepositoryName()); $this->assertEquals("repo_branch", $new->getRepositoryBranch()); $this->assertEquals("repo_url", $new->getRepositoryUrl()); $this->assertEquals("php_version", $new->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); } public function test_withRepositoryBranch() : void @@ -93,7 +102,8 @@ public function test_withRepositoryBranch() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $new = $project_config->withRepositoryBranch("test"); @@ -103,12 +113,14 @@ public function test_withRepositoryBranch() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); $this->assertEquals("name", $new->getName()); $this->assertEquals("repo_name", $new->getRepositoryName()); $this->assertEquals("test", $new->getRepositoryBranch()); $this->assertEquals("repo_url", $new->getRepositoryUrl()); $this->assertEquals("php_version", $new->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); } public function test_withRepositoryUrl() : void @@ -118,7 +130,8 @@ public function test_withRepositoryUrl() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $new = $project_config->withRepositoryUrl("test"); @@ -128,12 +141,14 @@ public function test_withRepositoryUrl() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); $this->assertEquals("name", $new->getName()); $this->assertEquals("repo_name", $new->getRepositoryName()); $this->assertEquals("repo_branch", $new->getRepositoryBranch()); $this->assertEquals( "test", $new->getRepositoryUrl()); $this->assertEquals("php_version", $new->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); } public function test_withPhpVersion() : void @@ -143,7 +158,8 @@ public function test_withPhpVersion() : void "repo_name", "repo_branch", "repo_url", - "php_version" + "php_version", + "ilias_version" ); $new = $project_config->withPhpVersion("test"); @@ -153,11 +169,41 @@ public function test_withPhpVersion() : void $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); $this->assertEquals("name", $new->getName()); $this->assertEquals("repo_name", $new->getRepositoryName()); $this->assertEquals("repo_branch", $new->getRepositoryBranch()); $this->assertEquals("repo_url", $new->getRepositoryUrl()); $this->assertEquals("test", $new->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); + } + + public function test_withIliasVersion() : void + { + $project_config = new ProjectConfig( + "name", + "repo_name", + "repo_branch", + "repo_url", + "php_version", + "ilias_version" + ); + + $new = $project_config->withIliasVersion("test"); + + $this->assertEquals("name", $project_config->getName()); + $this->assertEquals("repo_name", $project_config->getRepositoryName()); + $this->assertEquals("repo_branch", $project_config->getRepositoryBranch()); + $this->assertEquals("repo_url", $project_config->getRepositoryUrl()); + $this->assertEquals("php_version", $project_config->getPhpVersion()); + $this->assertEquals("ilias_version", $project_config->getIliasVersion()); + + $this->assertEquals("name", $new->getName()); + $this->assertEquals("repo_name", $new->getRepositoryName()); + $this->assertEquals("repo_branch", $new->getRepositoryBranch()); + $this->assertEquals("repo_url", $new->getRepositoryUrl()); + $this->assertEquals("php_version", $new->getPhpVersion()); + $this->assertEquals("test", $new->getIliasVersion()); } } \ No newline at end of file diff --git a/setup/conf/doil.conf b/setup/conf/doil.conf index 807266f5..7769dd3e 100755 --- a/setup/conf/doil.conf +++ b/setup/conf/doil.conf @@ -3,6 +3,7 @@ allowed_hosts=false https_proxy=false mail_password=ilias global_instances_path=/srv/instances +enable_office=false enable_keycloak=false keycloak_hostname=http://doil/keycloak keycloak_new_admin_password=admin diff --git a/setup/install.sh b/setup/install.sh index 9cc131ab..1c1f28c4 100755 --- a/setup/install.sh +++ b/setup/install.sh @@ -83,9 +83,10 @@ fi doil_status_okay ENABLE_KEYCLOAK=$(doil_get_conf enable_keycloak) +ENABLE_OFFICE=$(doil_get_conf enable_office) doil_status_send_message "Copy doil system" -doil_system_copy_doil "$ENABLE_KEYCLOAK" +doil_system_copy_doil "$ENABLE_KEYCLOAK" "$ENABLE_OFFICE" if [[ $? -ne 0 ]] then doil_status_failed @@ -162,6 +163,14 @@ then doil_status_send_message "Installing mail server" doil_system_install_mailserver doil_status_okay + + # start office server + if [[ "$ENABLE_OFFICE" == true ]] + then + doil_status_send_message "Installing office server" + doil_system_install_officeserver + doil_status_okay + fi fi doil_status_send_message "Ensure ~/.docker is owned by sudo user" diff --git a/setup/stack/config/master.cnf b/setup/stack/config/master.cnf index 2a891800..85c5e880 100755 --- a/setup/stack/config/master.cnf +++ b/setup/stack/config/master.cnf @@ -725,7 +725,11 @@ file_roots: prevent-super-global-replacement: - /srv/salt/states/prevent-super-global-replacement set-update-token: - - /srv/salt/states/set-update-token + - /srv/salt/states/set-update-token + enable-office: + - /srv/salt/states/enable-office + disable-office: + - /srv/salt/states/disable-office # The master_roots setting configures a master-only copy of the file_roots dictionary, diff --git a/setup/stack/states/disable-office/description.txt b/setup/stack/states/disable-office/description.txt new file mode 100644 index 00000000..58070d4c --- /dev/null +++ b/setup/stack/states/disable-office/description.txt @@ -0,0 +1 @@ +description = Deactivates the Office server. \ No newline at end of file diff --git a/setup/stack/states/disable-office/office/init.sls b/setup/stack/states/disable-office/office/init.sls new file mode 100644 index 00000000..4f020000 --- /dev/null +++ b/setup/stack/states/disable-office/office/init.sls @@ -0,0 +1,28 @@ +{% set ilias_version = salt['grains.get']('ilias_version', '9') %} + +{% if ilias_version | int < 10 %} +failure: + test.fail_without_changes: + - name: "OnlyOffice works only with ILIAS >= 10" + - failhard: True +{% endif %} + +disable_wopi: + mysql_query.run: + - database: ilias + - query: "UPDATE settings SET value = 0 where keyword = 'wopi_activated';" + +set_wopi_url: + mysql_query.run: + - database: ilias + - query: "DELETE FROM settings WHERE keyword = 'wopi_discovery_url';" + +drop_wopi_app_table: + mysql_query.run: + - database: ilias + - query: "DROP TABLE IF EXISTS wopi_app;" + +truncate_wopi_action_table: + mysql_query.run: + - database: ilias + - query: "DELETE FROM wopi_action;" \ No newline at end of file diff --git a/setup/stack/states/disable-office/top.sls b/setup/stack/states/disable-office/top.sls new file mode 100644 index 00000000..670435ff --- /dev/null +++ b/setup/stack/states/disable-office/top.sls @@ -0,0 +1,3 @@ +disable-office: + '*': + - office \ No newline at end of file diff --git a/setup/stack/states/enable-office/description.txt b/setup/stack/states/enable-office/description.txt new file mode 100644 index 00000000..18bc5a64 --- /dev/null +++ b/setup/stack/states/enable-office/description.txt @@ -0,0 +1 @@ +description = Enables the Office server. \ No newline at end of file diff --git a/setup/stack/states/enable-office/office/config/wopi.sql b/setup/stack/states/enable-office/office/config/wopi.sql new file mode 100644 index 00000000..a030f40e --- /dev/null +++ b/setup/stack/states/enable-office/office/config/wopi.sql @@ -0,0 +1,352 @@ +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: localhost Database: ilias +-- ------------------------------------------------------ +-- Server version 10.11.14-MariaDB-0+deb12u2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `wopi_app` +-- + +DROP TABLE IF EXISTS `wopi_app`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `wopi_app` ( + `id` int(11) NOT NULL, + `name` varchar(256) NOT NULL, + `favicon` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `wopi_app` +-- + +LOCK TABLES `wopi_app` WRITE; +/*!40000 ALTER TABLE `wopi_app` DISABLE KEYS */; +INSERT INTO `wopi_app` VALUES +(58,'Word','http://172.24.0.251/web-apps/apps/documenteditor/main/resources/img/favicon.ico'), +(59,'Excel','http://172.24.0.251/web-apps/apps/spreadsheeteditor/main/resources/img/favicon.ico'), +(60,'PowerPoint','http://172.24.0.251/web-apps/apps/presentationeditor/main/resources/img/favicon.ico'), +(61,'Pdf','http://172.24.0.251/web-apps/apps/pdfeditor/main/resources/img/favicon.ico'), +(62,'application/msword',NULL), +(63,'application/vnd.google-apps.document',NULL), +(64,'text/html',NULL), +(65,'text/markdown',NULL), +(66,'application/vnd.apple.pages',NULL), +(67,'application/x-iwork-pages-sffpages',NULL), +(68,'application/vnd.sun.xml.writer.template',NULL), +(69,'application/vnd.sun.xml.writer',NULL), +(70,'application/vnd.ms-works',NULL), +(71,'application/xml',NULL), +(72,'text/xml',NULL), +(73,'application/vnd.ms-word.document.macroenabled.12',NULL), +(74,'application/vnd.openxmlformats-officedocument.wordprocessingml.document',NULL), +(75,'application/vnd.ms-word.template.macroenabled.12',NULL), +(76,'application/vnd.openxmlformats-officedocument.wordprocessingml.template',NULL), +(77,'application/epub+zip',NULL), +(78,'application/vnd.oasis.opendocument.text',NULL), +(79,'application/vnd.oasis.opendocument.text-template',NULL), +(80,'application/rtf',NULL), +(81,'text/rtf',NULL), +(82,'text/plain',NULL), +(83,'application/vnd.google-apps.spreadsheet',NULL), +(84,'application/vnd.apple.numbers',NULL), +(85,'application/x-iwork-numbers-sffnumbers',NULL), +(86,'application/vnd.sun.xml.calc',NULL), +(87,'application/vnd.ms-excel',NULL), +(88,'text/csv',NULL), +(89,'application/vnd.oasis.opendocument.spreadsheet',NULL), +(90,'application/vnd.oasis.opendocument.spreadsheet-template',NULL), +(91,'text/tab-separated-values',NULL), +(92,'application/vnd.ms-excel.sheet.binary.macroenabled.12',NULL), +(93,'application/vnd.ms-excel.sheet.macroenabled.12',NULL), +(94,'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',NULL), +(95,'application/vnd.ms-excel.template.macroenabled.12',NULL), +(96,'application/vnd.openxmlformats-officedocument.spreadsheetml.template',NULL), +(97,'application/vnd.google-apps.presentation',NULL), +(98,'application/vnd.apple.keynote',NULL), +(99,'application/x-iwork-keynote-sffkey',NULL), +(100,'application/vnd.oasis.opendocument.graphics',NULL), +(101,'application/vnd.ms-powerpoint',NULL), +(102,'application/vnd.sun.xml.impress',NULL), +(103,'application/vnd.oasis.opendocument.presentation',NULL), +(104,'application/vnd.oasis.opendocument.presentation-template',NULL), +(105,'application/vnd.ms-powerpoint.template.macroenabled.12',NULL), +(106,'application/vnd.openxmlformats-officedocument.presentationml.template',NULL), +(107,'application/vnd.ms-powerpoint.slideshow.macroenabled.12',NULL), +(108,'application/vnd.openxmlformats-officedocument.presentationml.slideshow',NULL), +(109,'application/vnd.ms-powerpoint.presentation.macroenabled.12',NULL), +(110,'application/vnd.openxmlformats-officedocument.presentationml.presentation',NULL), +(111,'image/vnd.djvu',NULL), +(112,'application/oxps',NULL), +(113,'application/vnd.ms-xpsdocument',NULL), +(114,'application/pdf',NULL); +/*!40000 ALTER TABLE `wopi_app` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- +-- Table structure for table `wopi_action` +-- + +DROP TABLE IF EXISTS `wopi_action`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `wopi_action` ( + `id` int(11) NOT NULL, + `app_id` int(11) NOT NULL, + `name` varchar(256) NOT NULL, + `ext` varchar(256) NOT NULL, + `urlsrc` varchar(2048) NOT NULL, + `url_appendix` varchar(4000) DEFAULT NULL, + `target_ext` varchar(256) DEFAULT NULL, + `target_text` varchar(256) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `i1_idx` (`app_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `wopi_action` +-- + +LOCK TABLES `wopi_action` WRITE; +/*!40000 ALTER TABLE `wopi_action` DISABLE KEYS */; +INSERT INTO `wopi_action` VALUES +(405,58,'view','doc','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(406,58,'embedview','doc','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(407,58,'convert','doc','http://172.24.0.251/hosting/wopi/convert-and-edit/doc/docx','&','docx',NULL), +(408,58,'view','dot','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(409,58,'embedview','dot','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(410,58,'convert','dot','http://172.24.0.251/hosting/wopi/convert-and-edit/dot/docx','&','docx',NULL), +(411,58,'view','fodt','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(412,58,'embedview','fodt','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(413,58,'convert','fodt','http://172.24.0.251/hosting/wopi/convert-and-edit/fodt/docx','&','docx',NULL), +(414,58,'view','gdoc','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(415,58,'embedview','gdoc','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(416,58,'convert','gdoc','http://172.24.0.251/hosting/wopi/convert-and-edit/gdoc/docx','&','docx',NULL), +(417,58,'view','hml','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(418,58,'embedview','hml','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(419,58,'convert','hml','http://172.24.0.251/hosting/wopi/convert-and-edit/hml/docx','&','docx',NULL), +(420,58,'view','htm','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(421,58,'embedview','htm','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(422,58,'convert','htm','http://172.24.0.251/hosting/wopi/convert-and-edit/htm/docx','&','docx',NULL), +(423,58,'view','hwp','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(424,58,'embedview','hwp','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(425,58,'convert','hwp','http://172.24.0.251/hosting/wopi/convert-and-edit/hwp/docx','&','docx',NULL), +(426,58,'view','hwpx','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(427,58,'embedview','hwpx','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(428,58,'convert','hwpx','http://172.24.0.251/hosting/wopi/convert-and-edit/hwpx/docx','&','docx',NULL), +(429,58,'view','md','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(430,58,'embedview','md','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(431,58,'convert','md','http://172.24.0.251/hosting/wopi/convert-and-edit/md/docx','&','docx',NULL), +(432,58,'view','mht','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(433,58,'embedview','mht','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(434,58,'convert','mht','http://172.24.0.251/hosting/wopi/convert-and-edit/mht/docx','&','docx',NULL), +(435,58,'view','mhtml','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(436,58,'embedview','mhtml','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(437,58,'convert','mhtml','http://172.24.0.251/hosting/wopi/convert-and-edit/mhtml/docx','&','docx',NULL), +(438,58,'view','pages','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(439,58,'embedview','pages','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(440,58,'convert','pages','http://172.24.0.251/hosting/wopi/convert-and-edit/pages/docx','&','docx',NULL), +(441,58,'view','stw','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(442,58,'embedview','stw','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(443,58,'convert','stw','http://172.24.0.251/hosting/wopi/convert-and-edit/stw/docx','&','docx',NULL), +(444,58,'view','sxw','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(445,58,'embedview','sxw','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(446,58,'convert','sxw','http://172.24.0.251/hosting/wopi/convert-and-edit/sxw/docx','&','docx',NULL), +(447,58,'view','wps','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(448,58,'embedview','wps','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(449,58,'convert','wps','http://172.24.0.251/hosting/wopi/convert-and-edit/wps/docx','&','docx',NULL), +(450,58,'view','wpt','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(451,58,'embedview','wpt','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(452,58,'convert','wpt','http://172.24.0.251/hosting/wopi/convert-and-edit/wpt/docx','&','docx',NULL), +(453,58,'view','xml','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(454,58,'embedview','xml','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(455,58,'convert','xml','http://172.24.0.251/hosting/wopi/convert-and-edit/xml/docx','&','docx',NULL), +(456,58,'view','docm','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(457,58,'embedview','docm','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(458,58,'edit','docm','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(459,58,'view','docx','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(460,58,'embedview','docx','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(461,58,'edit','docx','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(462,58,'view','dotm','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(463,58,'embedview','dotm','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(464,58,'edit','dotm','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(465,58,'view','dotx','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(466,58,'embedview','dotx','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(467,58,'edit','dotx','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(468,58,'view','epub','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(469,58,'embedview','epub','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(470,58,'edit','epub','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(471,58,'view','fb2','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(472,58,'embedview','fb2','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(473,58,'edit','fb2','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(474,58,'view','html','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(475,58,'embedview','html','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(476,58,'edit','html','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(477,58,'view','odt','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(478,58,'embedview','odt','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(479,58,'edit','odt','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(480,58,'view','ott','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(481,58,'embedview','ott','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(482,58,'edit','ott','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(483,58,'view','rtf','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(484,58,'embedview','rtf','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(485,58,'edit','rtf','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(486,58,'view','txt','http://172.24.0.251/hosting/wopi/word/view','&',NULL,NULL), +(487,58,'embedview','txt','http://172.24.0.251/hosting/wopi/word/view','embed=1&&',NULL,NULL), +(488,58,'edit','txt','http://172.24.0.251/hosting/wopi/word/edit','&',NULL,NULL), +(489,59,'view','et','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(490,59,'embedview','et','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(491,59,'convert','et','http://172.24.0.251/hosting/wopi/convert-and-edit/et/xlsx','&','xlsx',NULL), +(492,59,'view','ett','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(493,59,'embedview','ett','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(494,59,'convert','ett','http://172.24.0.251/hosting/wopi/convert-and-edit/ett/xlsx','&','xlsx',NULL), +(495,59,'view','fods','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(496,59,'embedview','fods','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(497,59,'convert','fods','http://172.24.0.251/hosting/wopi/convert-and-edit/fods/xlsx','&','xlsx',NULL), +(498,59,'view','gsheet','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(499,59,'embedview','gsheet','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(500,59,'convert','gsheet','http://172.24.0.251/hosting/wopi/convert-and-edit/gsheet/xlsx','&','xlsx',NULL), +(501,59,'view','numbers','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(502,59,'embedview','numbers','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(503,59,'convert','numbers','http://172.24.0.251/hosting/wopi/convert-and-edit/numbers/xlsx','&','xlsx',NULL), +(504,59,'view','sxc','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(505,59,'embedview','sxc','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(506,59,'convert','sxc','http://172.24.0.251/hosting/wopi/convert-and-edit/sxc/xlsx','&','xlsx',NULL), +(507,59,'view','xls','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(508,59,'embedview','xls','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(509,59,'convert','xls','http://172.24.0.251/hosting/wopi/convert-and-edit/xls/xlsx','&','xlsx',NULL), +(510,59,'view','xlt','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(511,59,'embedview','xlt','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(512,59,'convert','xlt','http://172.24.0.251/hosting/wopi/convert-and-edit/xlt/xlsx','&','xlsx',NULL), +(513,59,'view','csv','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(514,59,'embedview','csv','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(515,59,'edit','csv','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(516,59,'view','ods','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(517,59,'embedview','ods','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(518,59,'edit','ods','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(519,59,'view','ots','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(520,59,'embedview','ots','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(521,59,'edit','ots','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(522,59,'view','tsv','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(523,59,'embedview','tsv','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(524,59,'edit','tsv','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(525,59,'view','xlsb','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(526,59,'embedview','xlsb','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(527,59,'edit','xlsb','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(528,59,'view','xlsm','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(529,59,'embedview','xlsm','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(530,59,'edit','xlsm','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(531,59,'view','xlsx','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(532,59,'embedview','xlsx','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(533,59,'edit','xlsx','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(534,59,'view','xltm','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(535,59,'embedview','xltm','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(536,59,'edit','xltm','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(537,59,'view','xltx','http://172.24.0.251/hosting/wopi/cell/view','&',NULL,NULL), +(538,59,'embedview','xltx','http://172.24.0.251/hosting/wopi/cell/view','embed=1&&',NULL,NULL), +(539,59,'edit','xltx','http://172.24.0.251/hosting/wopi/cell/edit','&',NULL,NULL), +(540,60,'view','dps','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(541,60,'embedview','dps','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(542,60,'convert','dps','http://172.24.0.251/hosting/wopi/convert-and-edit/dps/pptx','&','pptx',NULL), +(543,60,'view','dpt','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(544,60,'embedview','dpt','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(545,60,'convert','dpt','http://172.24.0.251/hosting/wopi/convert-and-edit/dpt/pptx','&','pptx',NULL), +(546,60,'view','fodp','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(547,60,'embedview','fodp','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(548,60,'convert','fodp','http://172.24.0.251/hosting/wopi/convert-and-edit/fodp/pptx','&','pptx',NULL), +(549,60,'view','gslides','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(550,60,'embedview','gslides','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(551,60,'convert','gslides','http://172.24.0.251/hosting/wopi/convert-and-edit/gslides/pptx','&','pptx',NULL), +(552,60,'view','key','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(553,60,'embedview','key','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(554,60,'convert','key','http://172.24.0.251/hosting/wopi/convert-and-edit/key/pptx','&','pptx',NULL), +(555,60,'view','odg','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(556,60,'embedview','odg','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(557,60,'convert','odg','http://172.24.0.251/hosting/wopi/convert-and-edit/odg/pptx','&','pptx',NULL), +(558,60,'view','pot','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(559,60,'embedview','pot','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(560,60,'convert','pot','http://172.24.0.251/hosting/wopi/convert-and-edit/pot/pptx','&','pptx',NULL), +(561,60,'view','pps','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(562,60,'embedview','pps','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(563,60,'convert','pps','http://172.24.0.251/hosting/wopi/convert-and-edit/pps/pptx','&','pptx',NULL), +(564,60,'view','ppt','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(565,60,'embedview','ppt','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(566,60,'convert','ppt','http://172.24.0.251/hosting/wopi/convert-and-edit/ppt/pptx','&','pptx',NULL), +(567,60,'view','sxi','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(568,60,'embedview','sxi','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(569,60,'convert','sxi','http://172.24.0.251/hosting/wopi/convert-and-edit/sxi/pptx','&','pptx',NULL), +(570,60,'view','odp','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(571,60,'embedview','odp','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(572,60,'edit','odp','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(573,60,'view','otp','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(574,60,'embedview','otp','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(575,60,'edit','otp','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(576,60,'view','potm','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(577,60,'embedview','potm','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(578,60,'edit','potm','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(579,60,'view','potx','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(580,60,'embedview','potx','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(581,60,'edit','potx','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(582,60,'view','ppsm','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(583,60,'embedview','ppsm','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(584,60,'edit','ppsm','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(585,60,'view','ppsx','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(586,60,'embedview','ppsx','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(587,60,'edit','ppsx','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(588,60,'view','pptm','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(589,60,'embedview','pptm','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(590,60,'edit','pptm','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(591,60,'view','pptx','http://172.24.0.251/hosting/wopi/slide/view','&',NULL,NULL), +(592,60,'embedview','pptx','http://172.24.0.251/hosting/wopi/slide/view','embed=1&&',NULL,NULL), +(593,60,'edit','pptx','http://172.24.0.251/hosting/wopi/slide/edit','&',NULL,NULL), +(594,61,'view','djvu','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(595,61,'embedview','djvu','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(596,61,'view','docxf','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(597,61,'embedview','docxf','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(598,61,'view','oform','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(599,61,'embedview','oform','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(600,61,'view','oxps','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(601,61,'embedview','oxps','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(602,61,'view','xps','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(603,61,'embedview','xps','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(604,61,'view','pdf','http://172.24.0.251/hosting/wopi/pdf/view','&',NULL,NULL), +(605,61,'embedview','pdf','http://172.24.0.251/hosting/wopi/pdf/view','embed=1&&',NULL,NULL), +(606,61,'edit','pdf','http://172.24.0.251/hosting/wopi/pdf/edit','&',NULL,NULL); +/*!40000 ALTER TABLE `wopi_action` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-05-27 11:51:36 \ No newline at end of file diff --git a/setup/stack/states/enable-office/office/init.sls b/setup/stack/states/enable-office/office/init.sls new file mode 100644 index 00000000..407f8544 --- /dev/null +++ b/setup/stack/states/enable-office/office/init.sls @@ -0,0 +1,28 @@ +{% set ilias_version = salt['grains.get']('ilias_version', '9') %} + +{% if ilias_version | int < 10 %} +failure: + test.fail_without_changes: + - name: "OnlyOffice works only with ILIAS >= 10" + - failhard: True +{% endif %} + +enable_wopi: + mysql_query.run: + - database: ilias + - query: "DELETE FROM settings WHERE keyword = 'wopi_activated';INSERT INTO settings (module, keyword, value) VALUES ('common', 'wopi_activated', 1);" + + +set_wopi_url: + mysql_query.run: + - database: ilias + - query: "DELETE FROM settings WHERE keyword = 'wopi_discovery_url';INSERT INTO settings (module, keyword, value) VALUES ('common', 'wopi_discovery_url', 'http://172.24.0.251/hosting/discovery');" + +/root/wopi.sql: + file.managed: + - source: salt://office/config/wopi.sql + - mode: "0444" + +import_wopi_app_sql: + cmd.run: + - name: mysql ilias < /root/wopi.sql \ No newline at end of file diff --git a/setup/stack/states/enable-office/top.sls b/setup/stack/states/enable-office/top.sls new file mode 100644 index 00000000..392a495f --- /dev/null +++ b/setup/stack/states/enable-office/top.sls @@ -0,0 +1,3 @@ +enable-office: + '*': + - office \ No newline at end of file diff --git a/setup/system.sh b/setup/system.sh index 6dc6ca98..daa020ba 100644 --- a/setup/system.sh +++ b/setup/system.sh @@ -61,7 +61,6 @@ function doil_system_remove() { doil_system_remove_doil_system_images doil_system_remove_networks doil_system_remove_volumes - doil_system_remove_user_doil_folders doil_system_remove_hosts_entry delgroup doil @@ -80,6 +79,8 @@ function doil_system_remove() { fi + doil_system_remove_user_doil_folders + if [ -d /etc/doil ] then rm -rf /etc/doil @@ -109,7 +110,7 @@ function doil_system_rm_system_instances() { } function doil_system_remove_all_images() { - docker rmi -f $(docker images -q --filter reference=doil[/,_]*) >/dev/null 2>&1 + docker image prune -af >/dev/null 2>&1 } function doil_system_remove_doil_system_images() { @@ -207,6 +208,8 @@ function doil_system_create_folder() { function doil_system_copy_doil() { enable_keycloak="$1" + enable_office="$2" + if [[ "$enable_keycloak" == true ]] then cp -r ${SCRIPT_DIR}/templates/keycloak /usr/local/lib/doil/server/ @@ -217,6 +220,16 @@ function doil_system_copy_doil() { fi fi + if [[ "$enable_office" == true ]] + then + cp -r ${SCRIPT_DIR}/templates/office /usr/local/lib/doil/server/ + else + if [ -d /usr/local/lib/doil/server/office ] + then + rm -rf /usr/local/lib/doil/server/office + fi + fi + cp ${SCRIPT_DIR}/doil.sh /usr/local/bin/doil cp -r ${SCRIPT_DIR}/templates/mail /usr/local/lib/doil/server/ cp -r ${SCRIPT_DIR}/templates/proxy /usr/local/lib/doil/server/ @@ -425,6 +438,13 @@ function doil_system_install_mailserver() { docker commit doil_mail doil_mail:stable 2>&1 > /var/log/doil/stream.log } +function doil_system_install_officeserver() { + cd /usr/local/lib/doil/server/office + BUILD=$(docker compose up -d 2>&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log + sleep 20 + docker exec -i doil_office bash -c "grep -qxF '172.24.0.254 doil' /etc/hosts || echo '172.24.0.254 doil' >> /etc/hosts" 2>&1 > /var/log/doil/stream.log +} + function doil_system_chown_dot_docker() { HOME=$(eval echo "~${SUDO_USER}") diff --git a/setup/templates/base/Dockerfile b/setup/templates/base/Dockerfile index bc270852..c0903f26 100755 --- a/setup/templates/base/Dockerfile +++ b/setup/templates/base/Dockerfile @@ -3,8 +3,10 @@ FROM debian:12 RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y cron default-jre apache2 mc vim nano less zip unzip git tree wget ftp curl wkhtmltopdf imagemagick ghostscript npm libapache2-mod-php8.2 php8.2-curl php8.2-gd php-json php8.2-mysql php8.2-readline php8.2-xsl php8.2-cli php8.2-zip php8.2-mbstring php8.2-soap php8.2-bcmath php8.2-imap apt-utils mariadb-server python3-mysqldb python3-dev default-libmysqlclient-dev build-essential pkg-config +RUN mkdir -m 755 -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN echo "Package: salt-*\nPin: version 3006.22\nPin-Priority: 1001" >> /etc/apt/preferences.d/salt-pin-1001 RUN apt-get update && apt-get install -y salt-minion RUN /opt/saltstack/salt/bin/python3 -m pip install --upgrade pip diff --git a/setup/templates/keycloak/Dockerfile b/setup/templates/keycloak/Dockerfile index 1ea186cc..d5cb12dd 100644 --- a/setup/templates/keycloak/Dockerfile +++ b/setup/templates/keycloak/Dockerfile @@ -16,8 +16,10 @@ RUN unzip keycloak-25.0.5.zip RUN mv keycloak-25.0.5 /opt/keycloak RUN rm keycloak-25.0.5.zip +RUN mkdir -m 755 -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN echo "Package: salt-*\nPin: version 3006.22\nPin-Priority: 1001" >> /etc/apt/preferences.d/salt-pin-1001 RUN apt-get update && apt-get install -y salt-minion RUN /opt/saltstack/salt/bin/python3 -m pip install --upgrade pip diff --git a/setup/templates/mail/Dockerfile b/setup/templates/mail/Dockerfile index 4db0666d..918c31bc 100755 --- a/setup/templates/mail/Dockerfile +++ b/setup/templates/mail/Dockerfile @@ -4,8 +4,10 @@ FROM debian:12 RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y vim nano curl less virt-what net-tools procps git debconf-utils python3-dev default-libmysqlclient-dev build-essential pkg-config +RUN mkdir -m 755 -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN echo "Package: salt-*\nPin: version 3006.22\nPin-Priority: 1001" >> /etc/apt/preferences.d/salt-pin-1001 RUN apt-get update && apt-get install -y salt-minion RUN /opt/saltstack/salt/bin/python3 -m pip install --upgrade pip diff --git a/setup/templates/office/Dockerfile b/setup/templates/office/Dockerfile new file mode 100644 index 00000000..2d225838 --- /dev/null +++ b/setup/templates/office/Dockerfile @@ -0,0 +1,143 @@ +ARG BASE_VERSION=24.04 + +ARG BASE_IMAGE=ubuntu:$BASE_VERSION + +FROM ${BASE_IMAGE} AS documentserver +LABEL maintainer="Ascensio System SIA " + +ARG BASE_VERSION +ARG PG_VERSION=16 +ARG PACKAGE_SUFFIX=t64 + +ENV OC_RELEASE_NUM=23 +ENV OC_RU_VER=7 +ENV OC_RU_REVISION_VER=0 +ENV OC_RESERVED_NUM=25 +ENV OC_RU_DATE=01 +ENV OC_PATH=${OC_RELEASE_NUM}${OC_RU_VER}0000 +ENV OC_FILE_SUFFIX=${OC_RELEASE_NUM}.${OC_RU_VER}.${OC_RU_REVISION_VER}.${OC_RESERVED_NUM}.${OC_RU_DATE} +ENV OC_VER_DIR=${OC_RELEASE_NUM}_${OC_RU_VER} +ENV OC_DOWNLOAD_URL=https://download.oracle.com/otn_software/linux/instantclient/${OC_PATH} + +ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 DEBIAN_FRONTEND=noninteractive PG_VERSION=${PG_VERSION} BASE_VERSION=${BASE_VERSION} + +ARG ONLYOFFICE_VALUE=onlyoffice +COPY fonts/ /usr/share/fonts/truetype/ + +RUN echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d && \ + apt-get -y update && \ + apt-get -yq install wget apt-transport-https gnupg locales lsb-release && \ + wget -q -O /etc/apt/sources.list.d/mssql-release.list "https://packages.microsoft.com/config/ubuntu/$BASE_VERSION/prod.list" && \ + wget -q -O /tmp/microsoft.asc https://packages.microsoft.com/keys/microsoft.asc && \ + apt-key add /tmp/microsoft.asc && \ + gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg < /tmp/microsoft.asc && \ + apt-get -y update && \ + locale-gen en_US.UTF-8 && \ + echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | debconf-set-selections && \ + ACCEPT_EULA=Y apt-get -yq install \ + adduser \ + apt-utils \ + bomstrip \ + certbot \ + cron \ + curl \ + htop \ + libaio1${PACKAGE_SUFFIX} \ + libasound2${PACKAGE_SUFFIX} \ + libboost-regex-dev \ + libcairo2 \ + libcurl3-gnutls \ + libcurl4 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libstdc++6 \ + libxml2 \ + libxss1 \ + libxtst6 \ + mssql-tools18 \ + mysql-client \ + nano \ + net-tools \ + netcat-openbsd \ + nginx-extras \ + postgresql \ + postgresql-client \ + pwgen \ + rabbitmq-server \ + redis-server \ + sudo \ + supervisor \ + ttf-mscorefonts-installer \ + unixodbc-dev \ + unzip \ + xvfb \ + xxd \ + zlib1g || dpkg --configure -a && \ + # Added dpkg --configure -a to handle installation issues with rabbitmq-server on arm64 architecture + if [ $(find /usr/share/fonts/truetype/msttcorefonts -maxdepth 1 -type f -iname '*.ttf' | wc -l) -lt 30 ]; \ + then echo 'msttcorefonts failed to download'; exit 1; fi && \ + echo "SERVER_ADDITIONAL_ERL_ARGS=\"+S 1:1\"" | tee -a /etc/rabbitmq/rabbitmq-env.conf && \ + sed -i "s/bind .*/bind 127.0.0.1/g" /etc/redis/redis.conf && \ + sed 's|\(application\/zip.*\)|\1\n application\/wasm wasm;|' -i /etc/nginx/mime.types && \ + pg_conftool $PG_VERSION main set listen_addresses 'localhost' && \ + service postgresql restart && \ + sudo -u postgres psql -c "CREATE USER $ONLYOFFICE_VALUE WITH password '$ONLYOFFICE_VALUE';" && \ + sudo -u postgres psql -c "CREATE DATABASE $ONLYOFFICE_VALUE OWNER $ONLYOFFICE_VALUE;" && \ + wget -O basic.zip ${OC_DOWNLOAD_URL}/instantclient-basic-linux.$(dpkg --print-architecture | sed 's/amd64/x64/')-${OC_FILE_SUFFIX}.zip && \ + wget -O sqlplus.zip ${OC_DOWNLOAD_URL}/instantclient-sqlplus-linux.$(dpkg --print-architecture | sed 's/amd64/x64/')-${OC_FILE_SUFFIX}.zip && \ + unzip -o basic.zip -d /usr/share && \ + unzip -o sqlplus.zip -d /usr/share && \ + mv /usr/share/instantclient_${OC_VER_DIR} /usr/share/instantclient && \ + find /usr/lib /lib -name "libaio.so.1$PACKAGE_SUFFIX" -exec bash -c 'ln -sf "$0" "$(dirname "$0")/libaio.so.1"' {} \; && \ + service postgresql stop && \ + service redis-server stop && \ + service rabbitmq-server stop && \ + service supervisor stop && \ + service nginx stop && \ + rm -rf /var/lib/apt/lists/* + +COPY config/supervisor/supervisor /etc/init.d/ +COPY config/supervisor/ds/*.conf /etc/supervisor/conf.d/ +COPY run-document-server.sh /app/ds/run-document-server.sh +COPY oracle/sqlplus /usr/bin/sqlplus + +EXPOSE 80 443 + +ARG COMPANY_NAME=onlyoffice +ARG PRODUCT_NAME=documentserver +ARG PRODUCT_EDITION= +ARG PACKAGE_VERSION= +ARG TARGETARCH +ARG PACKAGE_BASEURL="http://download.onlyoffice.com/install/documentserver/linux" + +ENV COMPANY_NAME=$COMPANY_NAME \ + PRODUCT_NAME=$PRODUCT_NAME \ + PRODUCT_EDITION=$PRODUCT_EDITION \ + DS_PLUGIN_INSTALLATION=false \ + DS_DOCKER_INSTALLATION=true + +RUN PACKAGE_FILE="${COMPANY_NAME}-${PRODUCT_NAME}${PRODUCT_EDITION}${PACKAGE_VERSION:+_$PACKAGE_VERSION}_${TARGETARCH:-$(dpkg --print-architecture)}.deb" && \ + wget -q -P /tmp "$PACKAGE_BASEURL/$PACKAGE_FILE" && \ + apt-get -y update && \ + service postgresql start && \ + apt-get -yq install /tmp/$PACKAGE_FILE && \ + if [ "${PRODUCT_EDITION}" != "-ee" ] && [ "${PRODUCT_EDITION}" != "-de" ]; then rm -f /etc/supervisor/conf.d/ds-adminpanel.conf && sed -i 's/,adminpanel//' /etc/supervisor/conf.d/ds.conf; fi && \ + PGPASSWORD=$ONLYOFFICE_VALUE dropdb -h localhost -p 5432 -U $ONLYOFFICE_VALUE $ONLYOFFICE_VALUE && \ + sudo -u postgres psql -c "DROP ROLE onlyoffice;" && \ + service postgresql stop && \ + chmod 755 /etc/init.d/supervisor && \ + sed "s/COMPANY_NAME/${COMPANY_NAME}/g" -i /etc/supervisor/conf.d/*.conf && \ + service supervisor stop && \ + chmod 755 /app/ds/*.sh && \ + printf "\nGO" >> "/var/www/$COMPANY_NAME/documentserver/server/schema/mssql/createdb.sql" && \ + printf "\nGO" >> "/var/www/$COMPANY_NAME/documentserver/server/schema/mssql/removetbl.sql" && \ + printf "\nexit" >> "/var/www/$COMPANY_NAME/documentserver/server/schema/oracle/createdb.sql" && \ + printf "\nexit" >> "/var/www/$COMPANY_NAME/documentserver/server/schema/oracle/removetbl.sql" && \ + rm -f /tmp/$PACKAGE_FILE && \ + rm -rf /var/log/$COMPANY_NAME && \ + rm -rf /var/lib/apt/lists/* + +VOLUME /var/log/$COMPANY_NAME /var/lib/$COMPANY_NAME /var/www/$COMPANY_NAME/Data /var/lib/postgresql /var/lib/rabbitmq /var/lib/redis /usr/share/fonts/truetype/custom + +ENTRYPOINT ["/app/ds/run-document-server.sh"] \ No newline at end of file diff --git a/setup/templates/office/config/supervisor/ds/ds-adminpanel.conf b/setup/templates/office/config/supervisor/ds/ds-adminpanel.conf new file mode 100644 index 00000000..82fe3496 --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds-adminpanel.conf @@ -0,0 +1,13 @@ +[program:adminpanel] +command=/var/www/COMPANY_NAME/documentserver/server/AdminPanel/server/adminpanel +directory=/var/www/COMPANY_NAME/documentserver/server/AdminPanel +user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/COMPANY_NAME/documentserver,NODE_DISABLE_COLORS=1,APPLICATION_NAME=COMPANY_NAME +stdout_logfile=/var/log/COMPANY_NAME/documentserver/adminpanel/out.log +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/var/log/COMPANY_NAME/documentserver/adminpanel/err.log +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=false +autorestart=false diff --git a/setup/templates/office/config/supervisor/ds/ds-converter.conf b/setup/templates/office/config/supervisor/ds/ds-converter.conf new file mode 100644 index 00000000..21daf989 --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds-converter.conf @@ -0,0 +1,13 @@ +[program:converter] +command=/var/www/COMPANY_NAME/documentserver/server/FileConverter/converter +directory=/var/www/COMPANY_NAME/documentserver/server/FileConverter +user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/COMPANY_NAME/documentserver,NODE_DISABLE_COLORS=1,APPLICATION_NAME=COMPANY_NAME,LD_LIBRARY_PATH=/var/www/COMPANY_NAME/documentserver/server/FileConverter/bin +stdout_logfile=/var/log/COMPANY_NAME/documentserver/converter/out.log +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/var/log/COMPANY_NAME/documentserver/converter/err.log +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true diff --git a/setup/templates/office/config/supervisor/ds/ds-docservice.conf b/setup/templates/office/config/supervisor/ds/ds-docservice.conf new file mode 100644 index 00000000..51c81ce8 --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds-docservice.conf @@ -0,0 +1,13 @@ +[program:docservice] +command=/var/www/COMPANY_NAME/documentserver/server/DocService/docservice +directory=/var/www/COMPANY_NAME/documentserver/server/DocService +user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/COMPANY_NAME/documentserver,NODE_DISABLE_COLORS=1,PKG_NATIVE_CACHE_PATH=/tmp/.cache,APPLICATION_NAME=COMPANY_NAME +stdout_logfile=/var/log/COMPANY_NAME/documentserver/docservice/out.log +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/var/log/COMPANY_NAME/documentserver/docservice/err.log +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=true +autorestart=true diff --git a/setup/templates/office/config/supervisor/ds/ds-example.conf b/setup/templates/office/config/supervisor/ds/ds-example.conf new file mode 100644 index 00000000..44fa6883 --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds-example.conf @@ -0,0 +1,14 @@ +[program:example] +command=/var/www/COMPANY_NAME/documentserver-example/example +directory=/var/www/COMPANY_NAME/documentserver-example/ +user=ds +environment=NODE_ENV=production-linux,NODE_CONFIG_DIR=/etc/COMPANY_NAME/documentserver-example,NODE_DISABLE_COLORS=1 +stdout_logfile=/var/log/COMPANY_NAME/documentserver-example/out.log +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/var/log/COMPANY_NAME/documentserver-example/err.log +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=false +autorestart=true +redirect_stderr=true diff --git a/setup/templates/office/config/supervisor/ds/ds-metrics.conf b/setup/templates/office/config/supervisor/ds/ds-metrics.conf new file mode 100644 index 00000000..d9c7576c --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds-metrics.conf @@ -0,0 +1,13 @@ +[program:metrics] +command=/var/www/COMPANY_NAME/documentserver/server/Metrics/metrics ./config/config.js +directory=/var/www/COMPANY_NAME/documentserver/server/Metrics +user=ds +environment=NODE_DISABLE_COLORS=1 +stdout_logfile=/var/log/COMPANY_NAME/documentserver/metrics/out.log +stdout_logfile_backups=0 +stdout_logfile_maxbytes=0 +stderr_logfile=/var/log/COMPANY_NAME/documentserver/metrics/err.log +stderr_logfile_backups=0 +stderr_logfile_maxbytes=0 +autostart=false +autorestart=false diff --git a/setup/templates/office/config/supervisor/ds/ds.conf b/setup/templates/office/config/supervisor/ds/ds.conf new file mode 100644 index 00000000..5e0c16b9 --- /dev/null +++ b/setup/templates/office/config/supervisor/ds/ds.conf @@ -0,0 +1,2 @@ +[group:ds] +programs=docservice,converter,metrics,example,adminpanel diff --git a/setup/templates/office/config/supervisor/supervisor b/setup/templates/office/config/supervisor/supervisor new file mode 100644 index 00000000..1e612e01 --- /dev/null +++ b/setup/templates/office/config/supervisor/supervisor @@ -0,0 +1,176 @@ +#! /bin/sh +# +# skeleton example file to build /etc/init.d/ scripts. +# This file should be used to construct scripts for /etc/init.d. +# +# Written by Miquel van Smoorenburg . +# Modified for Debian +# by Ian Murdock . +# Further changes by Javier Fernandez-Sanguino +# +# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl +# +### BEGIN INIT INFO +# Provides: supervisor +# Required-Start: $remote_fs $network $named +# Required-Stop: $remote_fs $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start/stop supervisor +# Description: Start/stop supervisor daemon and its configured +# subprocesses. +### END INIT INFO + +. /lib/lsb/init-functions + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/supervisord +NAME=supervisord +DESC=supervisor + +test -x $DAEMON || exit 0 + +LOGDIR=/var/log/supervisor +PIDFILE=/var/run/$NAME.pid +PS_COUNT=0 +DODTIME=5 # Time to wait for the server to die, in seconds + # If this value is set too low you might not + # let some servers to die gracefully and + # 'restart' will not work + +# Include supervisor defaults if available +if [ -f /etc/default/supervisor ] ; then + . /etc/default/supervisor +fi +DAEMON_OPTS="-c /etc/supervisor/supervisord.conf $DAEMON_OPTS" + +set -e + +running_pid() +{ + # Check if a given process pid's cmdline matches a given name + pid=$1 + name=$2 + [ -z "$pid" ] && return 1 + [ ! -d /proc/$pid ] && return 1 + (cat /proc/$pid/cmdline | tr "\000" "\n"|grep -q $name) || return 1 + return 0 +} + +running() +{ +# Check if the process is running looking at /proc +# (works for all users) + + # No pidfile, probably no daemon present + [ ! -f "$PIDFILE" ] && return 1 + # Obtain the pid and check it against the binary name + pid=`cat $PIDFILE` + running_pid $pid $DAEMON || return 1 + return 0 +} + +force_stop() { +# Forcefully kill the process + [ ! -f "$PIDFILE" ] && return + if running ; then + kill -15 $pid + # Is it really dead? + [ -n "$DODTIME" ] && sleep "$DODTIME"s + if running ; then + kill -9 $pid + [ -n "$DODTIME" ] && sleep "$DODTIME"s + if running ; then + echo "Cannot kill $LABEL (pid=$pid)!" + exit 1 + fi + fi + fi + rm -f $PIDFILE + return 0 +} + +get_pid() { + PS_COUNT=$(pgrep -fc $DAEMON || true) +} + +case "$1" in + start) + get_pid + if [ $PS_COUNT -eq 0 ]; then + rm -f "$PIDFILE" + fi + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile $PIDFILE \ + --startas $DAEMON -- $DAEMON_OPTS + test -f $PIDFILE || sleep 1 + if running ; then + echo "$NAME." + else + echo " ERROR." + fi + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE + echo "$NAME." + ;; + force-stop) + echo -n "Forcefully stopping $DESC: " + force_stop + if ! running ; then + echo "$NAME." + else + echo " ERROR." + fi + ;; + #reload) + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + # echo "Reloading $DESC configuration files." + # start-stop-daemon --stop --signal 1 --quiet --pidfile \ + # /var/run/$NAME.pid --exec $DAEMON + #;; + force-reload) + # + # If the "reload" option is implemented, move the "force-reload" + # option to the "reload" entry above. If not, "force-reload" is + # just the same as "restart" except that it does nothing if the + # daemon isn't already running. + # check wether $DAEMON is running. If so, restart + start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \ + --startas $DAEMON \ + && $0 restart \ + || exit 0 + ;; + restart) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE + [ -n "$DODTIME" ] && sleep $DODTIME + start-stop-daemon --start --quiet --pidfile $PIDFILE \ + --startas $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + status) + echo -n "$LABEL is " + if running ; then + echo "running" + else + echo " not running." + exit 1 + fi + ;; + *) + N=/etc/init.d/$NAME + # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/setup/templates/office/docker-compose.yml b/setup/templates/office/docker-compose.yml new file mode 100644 index 00000000..38feaef7 --- /dev/null +++ b/setup/templates/office/docker-compose.yml @@ -0,0 +1,99 @@ +services: + doil_office: + build: + context: . + image: onlyoffice/documentserver:9.4 + container_name: doil_office + depends_on: + - doil_postgresql + - doil_rabbitmq + labels: + doil.compose.doilinstance: "true" + environment: + - WOPI_ENABLED=true + - DB_TYPE=postgres + - DB_HOST=doil_postgresql + - DB_PORT=5432 + - DB_NAME=onlyoffice + - DB_USER=onlyoffice + - AMQP_URI=amqp://guest:guest@doil_rabbitmq + # Uncomment strings below to enable the JSON Web Token validation. + #- JWT_ENABLED=true + #- JWT_SECRET=secret + #- JWT_HEADER=Authorization + #- JWT_IN_BODY=true + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/info/info.json"] + interval: 30s + retries: 5 + start_period: 60s + timeout: 10s + stdin_open: true + restart: always + stop_grace_period: 60s + volumes: + - /var/www/onlyoffice/Data + - /var/log/onlyoffice + - /var/lib/onlyoffice/documentserver/App_Data/cache/files + - /var/www/onlyoffice/documentserver-example/public/files + - /usr/share/fonts + networks: + doil_proxy: + ipv4_address: 172.24.0.251 + salt_saltnet: + doil_office: + + doil_rabbitmq: + container_name: doil_rabbitmq + image: rabbitmq:3 + restart: always + labels: + doil.compose.doilinstance: "true" + expose: + - '5672' + healthcheck: + test: ["CMD", "rabbitmq-diagnostics", "status"] + interval: 10s + retries: 3 + start_period: 10s + timeout: 10s + networks: + doil_office: + + doil_postgresql: + container_name: doil_postgresql + image: postgres:15 + labels: + doil.compose.doilinstance: "true" + environment: + - POSTGRES_DB=onlyoffice + - POSTGRES_USER=onlyoffice + - POSTGRES_HOST_AUTH_METHOD=trust + restart: always + expose: + - '5432' + volumes: + - postgresql_data:/var/lib/postgresql + healthcheck: + test: ["CMD-SHELL", "pg_isready -U onlyoffice"] + interval: 10s + retries: 3 + start_period: 10s + timeout: 10s + networks: + doil_office: + +volumes: + postgresql_data: + +networks: + doil_proxy: + external: true + salt_saltnet: + external: true + doil_office: + name: doil_office + ipam: + driver: default + config: + - subnet: 172.26.0.0/16 \ No newline at end of file diff --git a/setup/templates/office/fonts/.placeholder b/setup/templates/office/fonts/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/setup/templates/office/oracle/sqlplus b/setup/templates/office/oracle/sqlplus new file mode 100644 index 00000000..4a7156c8 --- /dev/null +++ b/setup/templates/office/oracle/sqlplus @@ -0,0 +1,5 @@ +#!/bin/sh + +CLIENTDIR=/usr/share/instantclient +export LD_LIBRARY_PATH=$CLIENTDIR +$CLIENTDIR/sqlplus $@ \ No newline at end of file diff --git a/setup/templates/office/run-document-server.sh b/setup/templates/office/run-document-server.sh new file mode 100644 index 00000000..74673b5d --- /dev/null +++ b/setup/templates/office/run-document-server.sh @@ -0,0 +1,842 @@ +#!/bin/bash + +umask 0022 + +start_process() { + "$@" & + CHILD=$!; wait "$CHILD"; CHILD=""; +} + +function clean_exit { + [[ -z "$CHILD" ]] || kill -s SIGTERM "$CHILD" 2>/dev/null + if [ ${ONLYOFFICE_DATA_CONTAINER} == "false" ] && \ + [ ${ONLYOFFICE_DATA_CONTAINER_HOST} == "localhost" ]; then + /usr/bin/documentserver-prepare4shutdown.sh + fi + exit +} + +trap clean_exit SIGTERM SIGQUIT SIGABRT SIGINT + +# Define '**' behavior explicitly +shopt -s globstar + +APP_DIR="/var/www/${COMPANY_NAME}/documentserver" +DATA_DIR="/var/www/${COMPANY_NAME}/Data" +PRIVATE_DATA_DIR="${DATA_DIR}/.private" +DS_RELEASE_DATE="${PRIVATE_DATA_DIR}/ds_release_date" +LOG_DIR="/var/log/${COMPANY_NAME}" +DS_LOG_DIR="${LOG_DIR}/documentserver" +LIB_DIR="/var/lib/${COMPANY_NAME}" +DS_LIB_DIR="${LIB_DIR}/documentserver" +CONF_DIR="/etc/${COMPANY_NAME}/documentserver" +SUPERVISOR_CONF_DIR="/etc/supervisor/conf.d" +IS_UPGRADE="false" +PLUGINS_ENABLED=${PLUGINS_ENABLED:-true} + +ONLYOFFICE_DATA_CONTAINER=${ONLYOFFICE_DATA_CONTAINER:-false} +ONLYOFFICE_DATA_CONTAINER_HOST=${ONLYOFFICE_DATA_CONTAINER_HOST:-localhost} +ONLYOFFICE_DATA_CONTAINER_PORT=80 + +RELEASE_DATE="$(stat -c="%y" ${APP_DIR}/server/DocService/docservice | sed -r 's/=([0-9]+)-([0-9]+)-([0-9]+) ([0-9:.+ ]+)/\1-\2-\3/')"; +if [ -f ${DS_RELEASE_DATE} ]; then + PREV_RELEASE_DATE=$(head -n 1 ${DS_RELEASE_DATE}) +else + PREV_RELEASE_DATE="0" +fi + +if [ "${RELEASE_DATE}" != "${PREV_RELEASE_DATE}" ]; then + if [ ${ONLYOFFICE_DATA_CONTAINER} != "true" ]; then + IS_UPGRADE="true"; + fi +fi + +SSL_CERTIFICATES_DIR="/usr/share/ca-certificates/ds"; mkdir -p ${SSL_CERTIFICATES_DIR} +find "${DATA_DIR}/certs" -type f \( -iname '*.crt' -o -iname '*.pem' -o -iname '*.key' \) -exec cp -f {} "${SSL_CERTIFICATES_DIR}"/ \; +if find "${SSL_CERTIFICATES_DIR}" -maxdepth 1 -type f | read _; then + find "${SSL_CERTIFICATES_DIR}" -type f \( -iname '*.crt' -o -iname '*.pem' \) -exec chmod 644 {} \; + find "${SSL_CERTIFICATES_DIR}" -type f -iname '*.key' -exec chmod 400 {} \; +fi + +if [[ -z $SSL_CERTIFICATE_PATH ]] && [[ -f ${SSL_CERTIFICATES_DIR}/${COMPANY_NAME}.crt ]]; then + SSL_CERTIFICATE_PATH=${SSL_CERTIFICATES_DIR}/${COMPANY_NAME}.crt +else + SSL_CERTIFICATE_PATH=${SSL_CERTIFICATE_PATH:-${SSL_CERTIFICATES_DIR}/tls.crt} +fi +if [[ -z $SSL_KEY_PATH ]] && [[ -f ${SSL_CERTIFICATES_DIR}/${COMPANY_NAME}.key ]]; then + SSL_KEY_PATH=${SSL_CERTIFICATES_DIR}/${COMPANY_NAME}.key +else + SSL_KEY_PATH=${SSL_KEY_PATH:-${SSL_CERTIFICATES_DIR}/tls.key} +fi + +#When set, the well known "root" CAs will be extended with the extra certificates in file +NODE_EXTRA_CA_CERTS=${NODE_EXTRA_CA_CERTS:-${SSL_CERTIFICATES_DIR}/extra-ca-certs.pem} +if [[ -f ${NODE_EXTRA_CA_CERTS} ]]; then + NODE_EXTRA_ENVIRONMENT="${NODE_EXTRA_CA_CERTS}" +elif [[ -f ${SSL_CERTIFICATE_PATH} ]]; then + SSL_CERTIFICATE_SUBJECT=$(openssl x509 -subject -noout -in "${SSL_CERTIFICATE_PATH}" | sed 's/subject=//') + SSL_CERTIFICATE_ISSUER=$(openssl x509 -issuer -noout -in "${SSL_CERTIFICATE_PATH}" | sed 's/issuer=//') + + #Add self-signed certificate to trusted list for validating Docs requests to the test example + if [[ -n $SSL_CERTIFICATE_SUBJECT && $SSL_CERTIFICATE_SUBJECT == $SSL_CERTIFICATE_ISSUER ]]; then + NODE_EXTRA_ENVIRONMENT="${SSL_CERTIFICATE_PATH}" + fi +fi + +if [[ -n $NODE_EXTRA_ENVIRONMENT ]]; then + sed -i "s|^environment=.*$|&,NODE_EXTRA_CA_CERTS=${NODE_EXTRA_ENVIRONMENT}|" ${SUPERVISOR_CONF_DIR}/*.conf +fi + +CA_CERTIFICATES_PATH=${CA_CERTIFICATES_PATH:-${SSL_CERTIFICATES_DIR}/ca-certificates.pem} +SSL_DHPARAM_PATH=${SSL_DHPARAM_PATH:-${SSL_CERTIFICATES_DIR}/dhparam.pem} +SSL_VERIFY_CLIENT=${SSL_VERIFY_CLIENT:-off} +USE_UNAUTHORIZED_STORAGE=${USE_UNAUTHORIZED_STORAGE:-false} +ONLYOFFICE_HTTPS_HSTS_ENABLED=${ONLYOFFICE_HTTPS_HSTS_ENABLED:-true} +ONLYOFFICE_HTTPS_HSTS_MAXAGE=${ONLYOFFICE_HTTPS_HSTS_MAXAGE:-31536000} +SYSCONF_TEMPLATES_DIR="/app/ds/setup/config" + +NGINX_CONFD_PATH="/etc/nginx/conf.d"; +NGINX_ONLYOFFICE_PATH="${CONF_DIR}/nginx" +NGINX_ONLYOFFICE_CONF="${NGINX_ONLYOFFICE_PATH}/ds.conf" +NGINX_ONLYOFFICE_EXAMPLE_PATH="${CONF_DIR}-example/nginx" +NGINX_ONLYOFFICE_EXAMPLE_CONF="${NGINX_ONLYOFFICE_EXAMPLE_PATH}/includes/ds-example.conf" + +NGINX_CONFIG_PATH="/etc/nginx/nginx.conf" +NGINX_WORKER_PROCESSES=${NGINX_WORKER_PROCESSES:-1} +NGINX_ACCESS_LOG=${NGINX_ACCESS_LOG:-false} +# Limiting the maximum number of simultaneous connections due to possible memory shortage +LIMIT=$(ulimit -n); [ "$LIMIT" = "unlimited" ] || [ "$LIMIT" -gt 1048576 ] && LIMIT=1048576 +NGINX_WORKER_CONNECTIONS=${NGINX_WORKER_CONNECTIONS:-$LIMIT} +RABBIT_CONNECTIONS=${RABBIT_CONNECTIONS:-$LIMIT} + +JWT_ENABLED=${JWT_ENABLED:-true} + +# validate user's vars before using in json +if [ "${JWT_ENABLED}" == "true" ]; then + JWT_ENABLED="true" +else + JWT_ENABLED="false" +fi + +[ -z $JWT_SECRET ] && JWT_MESSAGE='JWT is enabled by default. A random secret is generated automatically. Run the command "docker exec $(sudo docker ps -q) sudo documentserver-jwt-status.sh" to get information about JWT.' + +JWT_SECRET=${JWT_SECRET:-$(pwgen -s 32)} +JWT_HEADER=${JWT_HEADER:-Authorization} +JWT_IN_BODY=${JWT_IN_BODY:-false} + +WOPI_ENABLED=${WOPI_ENABLED:-false} +ALLOW_META_IP_ADDRESS=${ALLOW_META_IP_ADDRESS:-false} +ALLOW_PRIVATE_IP_ADDRESS=${ALLOW_PRIVATE_IP_ADDRESS:-false} + +GENERATE_FONTS=${GENERATE_FONTS:-true} + +if [[ ${PRODUCT_NAME}${PRODUCT_EDITION} == "documentserver" ]]; then + REDIS_ENABLED=false +else + REDIS_ENABLED=true +fi + +[[ "${PRODUCT_EDITION}" =~ ^-(ee|de)$ ]] && ADMINPANEL_AVAILABLE=true || ADMINPANEL_AVAILABLE=false + +ONLYOFFICE_DEFAULT_CONFIG=${CONF_DIR}/local.json +ONLYOFFICE_LOG4JS_CONFIG=${CONF_DIR}/log4js/production.json +ONLYOFFICE_EXAMPLE_CONFIG=${CONF_DIR}-example/local.json + +JSON_BIN=${APP_DIR}/npm/json +JSON="${JSON_BIN} -q -f ${ONLYOFFICE_DEFAULT_CONFIG}" +JSON_LOG="${JSON_BIN} -q -f ${ONLYOFFICE_LOG4JS_CONFIG}" +JSON_EXAMPLE="${JSON_BIN} -q -f ${ONLYOFFICE_EXAMPLE_CONFIG}" + +LOCAL_SERVICES=() + +PG_ROOT=/var/lib/postgresql +PG_NAME=main +PGDATA=${PG_ROOT}/${PG_VERSION}/${PG_NAME} +PG_NEW_CLUSTER=false +RABBITMQ_DATA=/var/lib/rabbitmq +REDIS_DATA=/var/lib/redis + +if [ "${LETS_ENCRYPT_DOMAIN}" != "" -a "${LETS_ENCRYPT_MAIL}" != "" ]; then + LETSENCRYPT_ROOT_DIR="/etc/letsencrypt/live" + SSL_CERTIFICATE_PATH=${LETSENCRYPT_ROOT_DIR}/${LETS_ENCRYPT_DOMAIN}/fullchain.pem + SSL_KEY_PATH=${LETSENCRYPT_ROOT_DIR}/${LETS_ENCRYPT_DOMAIN}/privkey.pem +fi + +read_setting(){ + deprecated_var POSTGRESQL_SERVER_HOST DB_HOST + deprecated_var POSTGRESQL_SERVER_PORT DB_PORT + deprecated_var POSTGRESQL_SERVER_DB_NAME DB_NAME + deprecated_var POSTGRESQL_SERVER_USER DB_USER + deprecated_var POSTGRESQL_SERVER_PASS DB_PWD + deprecated_var RABBITMQ_SERVER_URL AMQP_URI + deprecated_var AMQP_SERVER_URL AMQP_URI + deprecated_var AMQP_SERVER_TYPE AMQP_TYPE + + METRICS_ENABLED="${METRICS_ENABLED:-false}" + METRICS_HOST="${METRICS_HOST:-localhost}" + METRICS_PORT="${METRICS_PORT:-8125}" + METRICS_PREFIX="${METRICS_PREFIX:-.ds}" + + DB_HOST=${DB_HOST:-${POSTGRESQL_SERVER_HOST:-$(${JSON} services.CoAuthoring.sql.dbHost)}} + DB_TYPE=${DB_TYPE:-$(${JSON} services.CoAuthoring.sql.type)} + case $DB_TYPE in + "postgres") + DB_PORT=${DB_PORT:-"5432"} + ;; + "mariadb"|"mysql") + DB_PORT=${DB_PORT:-"3306"} + ;; + "dameng") + DB_PORT=${DB_PORT:-"5236"} + ;; + "mssql") + DB_PORT=${DB_PORT:-"1433"} + ;; + "oracle") + DB_PORT=${DB_PORT:-"1521"} + ;; + "") + DB_PORT=${DB_PORT:-${POSTGRESQL_SERVER_PORT:-$(${JSON} services.CoAuthoring.sql.dbPort)}} + ;; + *) + echo "ERROR: unknown database type" + exit 1 + ;; + esac + DB_NAME=${DB_NAME:-${POSTGRESQL_SERVER_DB_NAME:-$(${JSON} services.CoAuthoring.sql.dbName)}} + DB_USER=${DB_USER:-${POSTGRESQL_SERVER_USER:-$(${JSON} services.CoAuthoring.sql.dbUser)}} + DB_PWD=${DB_PWD:-${POSTGRESQL_SERVER_PASS:-$(${JSON} services.CoAuthoring.sql.dbPass)}} + + RABBITMQ_SERVER_URL=${RABBITMQ_SERVER_URL:-$(${JSON} rabbitmq.url)} + AMQP_URI=${AMQP_URI:-${AMQP_SERVER_URL:-${RABBITMQ_SERVER_URL}}} + AMQP_TYPE=${AMQP_TYPE:-${AMQP_SERVER_TYPE:-rabbitmq}} + parse_rabbitmq_url ${AMQP_URI} + + REDIS_SERVER_HOST=${REDIS_SERVER_HOST:-$(${JSON} services.CoAuthoring.redis.host)} + REDIS_SERVER_PORT=${REDIS_SERVER_PORT:-6379} + + DS_LOG_LEVEL=${DS_LOG_LEVEL:-$(${JSON_LOG} categories.default.level)} +} + +deprecated_var() { + if [[ -n ${!1} ]]; then + echo "Variable $1 is deprecated. Use $2 instead." + fi +} + +parse_rabbitmq_url(){ + local amqp=$1 + + # extract the protocol + local proto="$(echo $amqp | grep :// | sed -e's,^\(.*://\).*,\1,g')" + # remove the protocol + local url="$(echo ${amqp/$proto/})" + + # extract the user and password (if any) + local userpass="`echo $url | grep @ | cut -d@ -f1`" + local pass=`echo $userpass | grep : | cut -d: -f2` + + local user + if [ -n "$pass" ]; then + user=`echo $userpass | grep : | cut -d: -f1` + else + user=$userpass + fi + + # extract the host + local hostport="$(echo ${url/$userpass@/} | cut -d/ -f1)" + # by request - try to extract the port + local port="$(echo $hostport | grep : | sed -r 's_^.*:+|/.*$__g')" + + local host + if [ -n "$port" ]; then + host=`echo $hostport | grep : | cut -d: -f1` + else + host=$hostport + port="5672" + fi + + # extract the path (if any) + local path="$(echo $url | grep / | cut -d/ -f2-)" + + AMQP_SERVER_PROTO=${proto:0:-3} + AMQP_SERVER_HOST=$host + AMQP_SERVER_USER=$user + AMQP_SERVER_PASS=$pass + AMQP_SERVER_PORT=$port +} + +waiting_for_connection(){ + until nc -z -w 3 "$1" "$2"; do + >&2 echo "Waiting for connection to the $1 host on port $2" + sleep 1 + done +} + +waiting_for_db_ready(){ + case $DB_TYPE in + "oracle") + ORACLE_SQL="sqlplus $DB_USER/$DB_PWD@//$DB_HOST:$DB_PORT/${DB_NAME}" + DB_TEST="echo \"SELECT version FROM V\$INSTANCE;\" | $ORACLE_SQL 2>/dev/null | grep \"Connected\" | wc -l" + ;; + *) + return + ;; + esac + + for (( i=1; i <= 10; i++ )); do + RES=$(eval $DB_TEST) + if [ "$RES" -ne "0" ]; then + echo "Database is ready" + break + fi + sleep 5 + done +} + +waiting_for_db(){ + waiting_for_connection $DB_HOST $DB_PORT + waiting_for_db_ready +} + +waiting_for_amqp(){ + waiting_for_connection ${AMQP_SERVER_HOST} ${AMQP_SERVER_PORT} +} + +waiting_for_redis(){ + waiting_for_connection ${REDIS_SERVER_HOST} ${REDIS_SERVER_PORT} +} +waiting_for_datacontainer(){ + waiting_for_connection ${ONLYOFFICE_DATA_CONTAINER_HOST} ${ONLYOFFICE_DATA_CONTAINER_PORT} +} + +update_statsd_settings(){ + ${JSON} -I -e "if(this.statsd===undefined)this.statsd={};" + ${JSON} -I -e "this.statsd.useMetrics = '${METRICS_ENABLED}'" + ${JSON} -I -e "this.statsd.host = '${METRICS_HOST}'" + ${JSON} -I -e "this.statsd.port = '${METRICS_PORT}'" + ${JSON} -I -e "this.statsd.prefix = '${METRICS_PREFIX}'" + sed -i -E "s/(autostart|autorestart)=.*$/\1=${METRICS_ENABLED}/g" ${SUPERVISOR_CONF_DIR}/ds-metrics.conf +} + +update_db_settings(){ + ${JSON} -I -e "this.services.CoAuthoring.sql.type = '${DB_TYPE}'" + ${JSON} -I -e "this.services.CoAuthoring.sql.dbHost = '${DB_HOST}'" + ${JSON} -I -e "this.services.CoAuthoring.sql.dbPort = '${DB_PORT}'" + ${JSON} -I -e "this.services.CoAuthoring.sql.dbName = '${DB_NAME}'" + ${JSON} -I -e "this.services.CoAuthoring.sql.dbUser = '${DB_USER}'" + ${JSON} -I -e "this.services.CoAuthoring.sql.dbPass = '${DB_PWD}'" +} + +update_rabbitmq_setting(){ + if [ "${AMQP_TYPE}" == "rabbitmq" ]; then + ${JSON} -I -e "if(this.queue===undefined)this.queue={};" + ${JSON} -I -e "this.queue.type = 'rabbitmq'" + ${JSON} -I -e "this.rabbitmq.url = '${AMQP_URI}'" + fi + + if [ "${AMQP_TYPE}" == "activemq" ]; then + ${JSON} -I -e "if(this.queue===undefined)this.queue={};" + ${JSON} -I -e "this.queue.type = 'activemq'" + ${JSON} -I -e "if(this.activemq===undefined)this.activemq={};" + ${JSON} -I -e "if(this.activemq.connectOptions===undefined)this.activemq.connectOptions={};" + + ${JSON} -I -e "this.activemq.connectOptions.host = '${AMQP_SERVER_HOST}'" + + if [ ! "${AMQP_SERVER_PORT}" == "" ]; then + ${JSON} -I -e "this.activemq.connectOptions.port = '${AMQP_SERVER_PORT}'" + else + ${JSON} -I -e "delete this.activemq.connectOptions.port" + fi + + if [ ! "${AMQP_SERVER_USER}" == "" ]; then + ${JSON} -I -e "this.activemq.connectOptions.username = '${AMQP_SERVER_USER}'" + else + ${JSON} -I -e "delete this.activemq.connectOptions.username" + fi + + if [ ! "${AMQP_SERVER_PASS}" == "" ]; then + ${JSON} -I -e "this.activemq.connectOptions.password = '${AMQP_SERVER_PASS}'" + else + ${JSON} -I -e "delete this.activemq.connectOptions.password" + fi + + case "${AMQP_SERVER_PROTO}" in + amqp+ssl|amqps) + ${JSON} -I -e "this.activemq.connectOptions.transport = 'tls'" + ;; + *) + ${JSON} -I -e "delete this.activemq.connectOptions.transport" + ;; + esac + fi +} + +update_redis_settings(){ + ${JSON} -I -e "if(this.services.CoAuthoring.redis===undefined)this.services.CoAuthoring.redis={};" + ${JSON} -I -e "this.services.CoAuthoring.redis.host = '${REDIS_SERVER_HOST}'" + ${JSON} -I -e "this.services.CoAuthoring.redis.port = '${REDIS_SERVER_PORT}'" + + ${JSON} -I -e "this.services.CoAuthoring.redis.options = { + ${REDIS_SERVER_USER:+username: '${REDIS_SERVER_USER}',} + ${REDIS_SERVER_PASS:+password: '${REDIS_SERVER_PASS}',} + ${REDIS_SERVER_DB:+database: '${REDIS_SERVER_DB}',} + }" +} + +update_ds_settings(){ + ${JSON} -I -e "this.services.CoAuthoring.token.enable.browser = ${JWT_ENABLED}" + ${JSON} -I -e "this.services.CoAuthoring.token.enable.request.inbox = ${JWT_ENABLED}" + ${JSON} -I -e "this.services.CoAuthoring.token.enable.request.outbox = ${JWT_ENABLED}" + + ${JSON} -I -e "this.services.CoAuthoring.secret.inbox.string = '${JWT_SECRET}'" + ${JSON} -I -e "this.services.CoAuthoring.secret.outbox.string = '${JWT_SECRET}'" + ${JSON} -I -e "this.services.CoAuthoring.secret.session.string = '${JWT_SECRET}'" + ${JSON} -I -e "this.services.CoAuthoring.secret.browser.string = '${JWT_SECRET}'" + + ${JSON} -I -e "this.services.CoAuthoring.token.inbox.header = '${JWT_HEADER}'" + ${JSON} -I -e "this.services.CoAuthoring.token.outbox.header = '${JWT_HEADER}'" + + ${JSON} -I -e "this.services.CoAuthoring.token.inbox.inBody = ${JWT_IN_BODY}" + ${JSON} -I -e "this.services.CoAuthoring.token.outbox.inBody = ${JWT_IN_BODY}" + + if [ -f "${ONLYOFFICE_EXAMPLE_CONFIG}" ]; then + ${JSON_EXAMPLE} -I -e "this.server.token.enable = ${JWT_ENABLED}" + ${JSON_EXAMPLE} -I -e "this.server.token.secret = '${JWT_SECRET}'" + ${JSON_EXAMPLE} -I -e "this.server.token.authorizationHeader = '${JWT_HEADER}'" + fi + + if [ "${USE_UNAUTHORIZED_STORAGE}" == "true" ]; then + ${JSON} -I -e "if(this.services.CoAuthoring.requestDefaults===undefined)this.services.CoAuthoring.requestDefaults={}" + ${JSON} -I -e "if(this.services.CoAuthoring.requestDefaults.rejectUnauthorized===undefined)this.services.CoAuthoring.requestDefaults.rejectUnauthorized=false" + fi + + WOPI_PRIVATE_KEY="${DATA_DIR}/wopi_private.key" + WOPI_PUBLIC_KEY="${DATA_DIR}/wopi_public.key" + + [ ! -f "${WOPI_PRIVATE_KEY}" ] && echo -n "Generating WOPI private key..." && openssl genpkey -algorithm RSA -outform PEM -out "${WOPI_PRIVATE_KEY}" >/dev/null 2>&1 && echo "Done" + [ ! -f "${WOPI_PUBLIC_KEY}" ] && echo -n "Generating WOPI public key..." && openssl rsa -RSAPublicKey_out -in "${WOPI_PRIVATE_KEY}" -outform "MS PUBLICKEYBLOB" -out "${WOPI_PUBLIC_KEY}" >/dev/null 2>&1 && echo "Done" + WOPI_MODULUS=$(openssl rsa -pubin -inform "MS PUBLICKEYBLOB" -modulus -noout -in "${WOPI_PUBLIC_KEY}" | sed 's/Modulus=//' | xxd -r -p | openssl base64 -A) + WOPI_EXPONENT=$(openssl rsa -pubin -inform "MS PUBLICKEYBLOB" -text -noout -in "${WOPI_PUBLIC_KEY}" | grep -oP '(?<=Exponent: )\d+') + + ${JSON} -I -e "if(this.wopi===undefined)this.wopi={};" + ${JSON} -I -e "this.wopi.enable = ${WOPI_ENABLED}" + ${JSON} -I -e "this.wopi.privateKey = '$(awk '{printf "%s\\n", $0}' ${WOPI_PRIVATE_KEY})'" + ${JSON} -I -e "this.wopi.privateKeyOld = '$(awk '{printf "%s\\n", $0}' ${WOPI_PRIVATE_KEY})'" + ${JSON} -I -e "this.wopi.publicKey = '$(openssl base64 -in ${WOPI_PUBLIC_KEY} -A)'" + ${JSON} -I -e "this.wopi.publicKeyOld = '$(openssl base64 -in ${WOPI_PUBLIC_KEY} -A)'" + ${JSON} -I -e "this.wopi.modulus = '${WOPI_MODULUS}'" + ${JSON} -I -e "this.wopi.modulusOld = '${WOPI_MODULUS}'" + ${JSON} -I -e "this.wopi.exponent = ${WOPI_EXPONENT}" + ${JSON} -I -e "this.wopi.exponentOld = ${WOPI_EXPONENT}" + + if [ "${ALLOW_META_IP_ADDRESS}" = "true" ] || [ "${ALLOW_PRIVATE_IP_ADDRESS}" = "true" ]; then + ${JSON} -I -e "if(this.services.CoAuthoring['request-filtering-agent']===undefined)this.services.CoAuthoring['request-filtering-agent']={}" + [ "${ALLOW_META_IP_ADDRESS}" = "true" ] && ${JSON} -I -e "this.services.CoAuthoring['request-filtering-agent'].allowMetaIPAddress = true" + [ "${ALLOW_PRIVATE_IP_ADDRESS}" = "true" ] && ${JSON} -I -e "this.services.CoAuthoring['request-filtering-agent'].allowPrivateIPAddress = true" + fi +} + +create_postgresql_cluster(){ + local pg_conf_dir=/etc/postgresql/${PG_VERSION}/${PG_NAME} + local postgresql_conf=$pg_conf_dir/postgresql.conf + local hba_conf=$pg_conf_dir/pg_hba.conf + + mv $postgresql_conf $postgresql_conf.backup + mv $hba_conf $hba_conf.backup + + pg_createcluster ${PG_VERSION} ${PG_NAME} +} + +create_postgresql_db(){ + sudo -u postgres psql -c "CREATE USER $DB_USER WITH password '"$DB_PWD"';" + sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" +} + +create_mssql_db(){ + ${MSSQL/ -d $DB_NAME/} -b -Q "IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '$DB_NAME') BEGIN CREATE DATABASE [$DB_NAME]; END" +} + +create_db_tbl() { + case $DB_TYPE in + "postgres") + create_postgresql_tbl + ;; + "mariadb"|"mysql") + create_mysql_tbl + ;; + "mssql") + create_mssql_tbl + ;; + "oracle") + create_oracle_tbl + ;; + esac +} + +upgrade_db_tbl() { + case $DB_TYPE in + "postgres") + upgrade_postgresql_tbl + ;; + "mariadb"|"mysql") + upgrade_mysql_tbl + ;; + "mssql") + upgrade_mssql_tbl + ;; + "oracle") + upgrade_oracle_tbl + ;; + esac +} + +postgresql_check_schema(){ + DB_SCHEMA=${DB_SCHEMA:-$(${JSON} services.CoAuthoring.sql.pgPoolExtraOptions.options 2>/dev/null | sed -n 's/.*search_path=\([^, ]*\).*/\1/p')} + if [ -n "${DB_SCHEMA}" ]; then + export PGOPTIONS="-c search_path=${DB_SCHEMA}" + $PSQL -c "CREATE SCHEMA IF NOT EXISTS ${DB_SCHEMA};" >/dev/null 2>&1 + ${JSON} -I -e "this.services.CoAuthoring.sql.pgPoolExtraOptions ||= {}; this.services.CoAuthoring.sql.pgPoolExtraOptions.options = '${PGOPTIONS}'" + fi +} + +mssql_check_schema(){ + if [ -n "${DB_SCHEMA}" ]; then + ${MSSQL} -b -Q "DECLARE @s sysname=N'${DB_SCHEMA}'; IF SCHEMA_ID(@s) IS NULL BEGIN DECLARE @sql nvarchar(max); SET @sql=N'CREATE SCHEMA '+QUOTENAME(@s)+N' AUTHORIZATION '+QUOTENAME(N'${DB_USER}'); EXEC(@sql); END" + ${MSSQL} -b -Q "DECLARE @s sysname=N'${DB_SCHEMA}'; DECLARE @u sysname=N'${DB_USER}'; IF USER_ID(@u) IS NOT NULL BEGIN DECLARE @sql nvarchar(max); SET @sql=N'ALTER USER '+QUOTENAME(@u)+N' WITH DEFAULT_SCHEMA = '+QUOTENAME(@s); EXEC(@sql); END" + fi +} + +upgrade_postgresql_tbl() { + if [ -n "$DB_PWD" ]; then + export PGPASSWORD=$DB_PWD + fi + + PSQL="psql -q -h$DB_HOST -p$DB_PORT -d$DB_NAME -U$DB_USER -w" + + postgresql_check_schema + $PSQL -f "$APP_DIR/server/schema/postgresql/removetbl.sql" + $PSQL -f "$APP_DIR/server/schema/postgresql/createdb.sql" +} + +upgrade_mysql_tbl() { + CONNECTION_PARAMS="-h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PWD -w" + MYSQL="mysql -q $CONNECTION_PARAMS" + + $MYSQL $DB_NAME < "$APP_DIR/server/schema/mysql/removetbl.sql" >/dev/null 2>&1 + $MYSQL $DB_NAME < "$APP_DIR/server/schema/mysql/createdb.sql" >/dev/null 2>&1 +} + +upgrade_mssql_tbl() { + if [ -n "$DB_PWD" ]; then + export SQLCMDPASSWORD=$DB_PWD + fi + + MSSQL="/opt/mssql-tools18/bin/sqlcmd -S $DB_HOST,$DB_PORT -d $DB_NAME -U $DB_USER -C" + + mssql_check_schema + $MSSQL < "$APP_DIR/server/schema/mssql/removetbl.sql" >/dev/null 2>&1 + $MSSQL < "$APP_DIR/server/schema/mssql/createdb.sql" >/dev/null 2>&1 +} + +upgrade_oracle_tbl() { + ORACLE_SQL="sqlplus $DB_USER/$DB_PWD@//$DB_HOST:$DB_PORT/${DB_NAME}" + + $ORACLE_SQL @$APP_DIR/server/schema/oracle/removetbl.sql >/dev/null 2>&1 + $ORACLE_SQL @$APP_DIR/server/schema/oracle/createdb.sql >/dev/null 2>&1 +} + +create_postgresql_tbl() { + if [ -n "$DB_PWD" ]; then + export PGPASSWORD=$DB_PWD + fi + + PSQL="psql -q -h$DB_HOST -p$DB_PORT -d$DB_NAME -U$DB_USER -w" + + postgresql_check_schema + $PSQL -f "$APP_DIR/server/schema/postgresql/createdb.sql" +} + +create_mysql_tbl() { + CONNECTION_PARAMS="-h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PWD -w" + MYSQL="mysql -q $CONNECTION_PARAMS" + + # Create db on remote server + $MYSQL -e "CREATE DATABASE IF NOT EXISTS $DB_NAME DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" >/dev/null 2>&1 + + $MYSQL $DB_NAME < "$APP_DIR/server/schema/mysql/createdb.sql" >/dev/null 2>&1 +} + +create_mssql_tbl() { + if [ -n "$DB_PWD" ]; then + export SQLCMDPASSWORD=$DB_PWD + fi + + MSSQL="/opt/mssql-tools18/bin/sqlcmd -S $DB_HOST,$DB_PORT -d $DB_NAME -U $DB_USER -C" + + create_mssql_db + mssql_check_schema + $MSSQL < "$APP_DIR/server/schema/mssql/createdb.sql" >/dev/null 2>&1 +} + +create_oracle_tbl() { + ORACLE_SQL="sqlplus $DB_USER/$DB_PWD@//$DB_HOST:$DB_PORT/${DB_NAME}" + + $ORACLE_SQL @$APP_DIR/server/schema/oracle/createdb.sql >/dev/null 2>&1 +} + +update_welcome_page() { + WELCOME_PAGE="${APP_DIR}-example/welcome/docker.html" + EXAMPLE_DISABLED_PAGE="${APP_DIR}-example/welcome/example-disabled.html" + if ${ADMINPANEL_AVAILABLE}; then + ADMIN_DISABLED_PAGE="${APP_DIR}-example/welcome/admin-disabled.html" + sed -Ei 's#sudo systemctl start ds-(adminpanel|example)#sudo docker exec $(sudo docker ps -q) supervisorctl start ds:\1#g' "$ADMIN_DISABLED_PAGE" "$EXAMPLE_DISABLED_PAGE" + else + sed -Ei 's#sudo systemctl start ds-example#sudo docker exec $(sudo docker ps -q) supervisorctl start ds:example#g' "$EXAMPLE_DISABLED_PAGE" + fi + + TARGET_PAGES="$WELCOME_PAGE $EXAMPLE_DISABLED_PAGE${ADMIN_DISABLED_PAGE:+ $ADMIN_DISABLED_PAGE}" + if [[ -e $WELCOME_PAGE ]]; then + DOCKER_CONTAINER_ID=$(basename $(cat /proc/1/cpuset)) + (( ${#DOCKER_CONTAINER_ID} < 12 )) && DOCKER_CONTAINER_ID=$(hostname) + if (( ${#DOCKER_CONTAINER_ID} >= 12 )); then + if [[ -x $(command -v docker) ]]; then + DOCKER_CONTAINER_NAME=$(docker inspect --format="{{.Name}}" $DOCKER_CONTAINER_ID) + sed 's/$(sudo docker ps -q)/'"${DOCKER_CONTAINER_NAME#/}"'/' -i ${TARGET_PAGES} + JWT_MESSAGE=$(echo $JWT_MESSAGE | sed 's/$(sudo docker ps -q)/'"${DOCKER_CONTAINER_NAME#/}"'/') + else + sed 's/$(sudo docker ps -q)/'"${DOCKER_CONTAINER_ID::12}"'/' -i ${TARGET_PAGES} + JWT_MESSAGE=$(echo $JWT_MESSAGE | sed 's/$(sudo docker ps -q)/'"${DOCKER_CONTAINER_ID::12}"'/') + fi + fi + fi +} + +update_nginx_settings(){ + # Set up nginx + sed 's/^worker_processes.*/'"worker_processes ${NGINX_WORKER_PROCESSES};"'/' -i ${NGINX_CONFIG_PATH} + sed 's/worker_connections.*/'"worker_connections ${NGINX_WORKER_CONNECTIONS};"'/' -i ${NGINX_CONFIG_PATH} + + if [ "${NGINX_ACCESS_LOG}" = "true" ]; then + touch "${DS_LOG_DIR}/nginx.access.log" + sed -ri 's|^\s*access_log\b.*;|access_log '"${DS_LOG_DIR}"'/nginx.access.log;|' "${NGINX_CONFIG_PATH}" "${NGINX_ONLYOFFICE_PATH}/includes/ds-common.conf" 2>/dev/null + else + sed -ri 's|^\s*access_log\b.*;|access_log off;|' "${NGINX_CONFIG_PATH}" + fi + + # setup HTTPS + if [ -f "${SSL_CERTIFICATE_PATH}" -a -f "${SSL_KEY_PATH}" ]; then + cp -f ${NGINX_ONLYOFFICE_PATH}/ds-ssl.conf.tmpl ${NGINX_ONLYOFFICE_CONF} + + # configure nginx + sed 's,{{SSL_CERTIFICATE_PATH}},'"${SSL_CERTIFICATE_PATH}"',' -i ${NGINX_ONLYOFFICE_CONF} + sed 's,{{SSL_KEY_PATH}},'"${SSL_KEY_PATH}"',' -i ${NGINX_ONLYOFFICE_CONF} + + # turn on http2 + sed 's,\(443 ssl\),\1 http2,' -i ${NGINX_ONLYOFFICE_CONF} + + # if dhparam path is valid, add to the config, otherwise remove the option + if [ -r "${SSL_DHPARAM_PATH}" ]; then + sed 's,\(\#* *\)\?\(ssl_dhparam \).*\(;\)$,'"\2${SSL_DHPARAM_PATH}\3"',' -i ${NGINX_ONLYOFFICE_CONF} + else + sed '/ssl_dhparam/d' -i ${NGINX_ONLYOFFICE_CONF} + fi + + sed 's,\(ssl_verify_client \).*\(;\)$,'"\1${SSL_VERIFY_CLIENT}\2"',' -i ${NGINX_ONLYOFFICE_CONF} + + if [ -f "${CA_CERTIFICATES_PATH}" ]; then + sed '/ssl_verify_client/a '"ssl_client_certificate ${CA_CERTIFICATES_PATH}"';' -i ${NGINX_ONLYOFFICE_CONF} + fi + + if [ "${ONLYOFFICE_HTTPS_HSTS_ENABLED}" == "true" ]; then + sed 's,\(max-age=\).*\(;\)$,'"\1${ONLYOFFICE_HTTPS_HSTS_MAXAGE}\2"',' -i ${NGINX_ONLYOFFICE_CONF} + else + sed '/max-age=/d' -i ${NGINX_ONLYOFFICE_CONF} + fi + else + ln -sf ${NGINX_ONLYOFFICE_PATH}/ds.conf.tmpl ${NGINX_ONLYOFFICE_CONF} + fi + + # check if ipv6 supported otherwise remove it from nginx config + if [ ! -f /proc/net/if_inet6 ]; then + sed '/listen\s\+\[::[0-9]*\].\+/d' -i $NGINX_ONLYOFFICE_CONF + fi + + if [ -f "${NGINX_ONLYOFFICE_EXAMPLE_CONF}" ]; then + sed 's/linux/docker/' -i ${NGINX_ONLYOFFICE_EXAMPLE_CONF} + fi + + start_process documentserver-update-securelink.sh -s ${SECURE_LINK_SECRET:-$(pwgen -s 20)} -r false +} + +update_log_settings(){ + ${JSON_LOG} -I -e "this.categories.default.level = '${DS_LOG_LEVEL}'" +} + +update_logrotate_settings(){ + sed 's|\(^su\b\).*|\1 root root|' -i /etc/logrotate.conf +} + +update_release_date(){ + mkdir -p ${PRIVATE_DATA_DIR} + echo ${RELEASE_DATE} > ${DS_RELEASE_DATE} +} + +# create base folders +for SUPERVISOR_CONF in "${SUPERVISOR_CONF_DIR}"/ds-*.conf; do + SERVICE_NAME=$(sed "s|^${SUPERVISOR_CONF_DIR}/ds-||; s|\.conf$||" <<<"$SUPERVISOR_CONF") + mkdir -p "$DS_LOG_DIR/$SERVICE_NAME" && touch "$DS_LOG_DIR/$SERVICE_NAME"/{out,err}.log +done +mkdir -p "${DS_LOG_DIR}-example" && touch "${DS_LOG_DIR}-example"/{out,err}.log + +# create app folders +for i in ${DS_LIB_DIR}/App_Data/cache/files ${DS_LIB_DIR}/App_Data/docbuilder ${DS_LIB_DIR}-example/files; do + mkdir -p "$i" +done + +# change folder rights +chown ds:ds "${DATA_DIR}" +for i in ${DS_LOG_DIR} ${DS_LOG_DIR}-example ${LIB_DIR}; do + chown -R ds:ds "$i" + chmod -R 755 "$i" +done + +# Bug 75324 - Update permissions for runtime.json +AI_CONFIG_FILE="${DATA_DIR}/runtime.json" +[ -f "${AI_CONFIG_FILE}" ] && { chown ds:ds "${AI_CONFIG_FILE}" && chmod 644 "${AI_CONFIG_FILE}"; } + +if [ ${ONLYOFFICE_DATA_CONTAINER_HOST} = "localhost" ]; then + + read_setting + + if [ $METRICS_ENABLED = "true" ]; then + update_statsd_settings + fi + + update_welcome_page + + update_log_settings + + update_ds_settings + + # update settings by env variables + if [ $DB_HOST != "localhost" ]; then + update_db_settings + waiting_for_db + create_db_tbl + else + # change rights for postgres directory + chown -R postgres:postgres ${PG_ROOT} + chmod -R 700 ${PG_ROOT} + + # create new db if it isn't exist + if [ ! -d ${PGDATA} ]; then + create_postgresql_cluster + PG_NEW_CLUSTER=true + fi + LOCAL_SERVICES+=("postgresql") + fi + + if [ ${AMQP_SERVER_HOST} != "localhost" ]; then + update_rabbitmq_setting + else + # change rights for rabbitmq directory + chown -R rabbitmq:rabbitmq ${RABBITMQ_DATA} + chmod -R go=rX,u=rwX ${RABBITMQ_DATA} + if [ -f ${RABBITMQ_DATA}/.erlang.cookie ]; then + chmod 400 ${RABBITMQ_DATA}/.erlang.cookie + fi + + sed -i '/^[[:space:]]*ulimit[[:space:]]\+-n[[:space:]]\+/d' /etc/default/rabbitmq-server + printf 'ulimit -n %s\n' "${RABBIT_CONNECTIONS}" >> /etc/default/rabbitmq-server + + LOCAL_SERVICES+=("rabbitmq-server") + # allow Rabbitmq startup after container kill + rm -rf /var/run/rabbitmq + fi + + if [ ${REDIS_ENABLED} = "true" ]; then + if [ ${REDIS_SERVER_HOST} != "localhost" ]; then + update_redis_settings + else + # change rights for redis directory + chown -R redis:redis ${REDIS_DATA} + chmod -R 750 ${REDIS_DATA} + + LOCAL_SERVICES+=("redis-server") + fi + fi +else + # no need to update settings just wait for remote data + waiting_for_datacontainer + + # read settings after the data container in ready state + # to prevent get unconfigured data + read_setting + + update_welcome_page +fi + +find /etc/${COMPANY_NAME} ! -path '*logrotate*' -exec chown ds:ds {} \; + +#start needed local services +for i in ${LOCAL_SERVICES[@]}; do + service $i start +done + +PG_DB_EXISTS=$(PGPASSWORD="$DB_PWD" psql -h ${DB_HOST} -p${DB_PORT} -U "${DB_USER}" -tAc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}';" 2>/dev/null) +if [ ${PG_NEW_CLUSTER} = "true" ] || [ "${PG_DB_EXISTS}" != "1" ]; then + create_postgresql_db + create_postgresql_tbl +fi + +if [ ${ONLYOFFICE_DATA_CONTAINER} != "true" ]; then + waiting_for_db + waiting_for_amqp + if [ ${REDIS_ENABLED} = "true" ]; then + waiting_for_redis + fi + + if [ "${IS_UPGRADE}" = "true" ]; then + upgrade_db_tbl + update_release_date + fi + + update_nginx_settings + + if [ "${PLUGINS_ENABLED}" = "true" ]; then + ( documentserver-pluginsmanager.sh -r false --update="${APP_DIR}/sdkjs-plugins/plugin-list-default.json" >/dev/null; echo "[pluginsmanager] Plugins initialization finished" >/proc/1/fd/1 ) & + fi + + ${ADMINPANEL_AVAILABLE} && [ "${ADMINPANEL_ENABLED:-false}" = "true" ] && sed -i 's,autostart=false,autostart=true,' ${SUPERVISOR_CONF_DIR}/ds-adminpanel.conf + [ "${EXAMPLE_ENABLED:-false}" = "true" ] && sed -i 's,autostart=false,autostart=true,' ${SUPERVISOR_CONF_DIR}/ds-example.conf + service supervisor start + + # start cron to enable log rotating + update_logrotate_settings + service cron start +fi + +# Fix to resolve the `unknown "cache_tag" variable` error +start_process documentserver-flush-cache.sh -r false + +# nginx used as a proxy, and as data container status service. +# it run in all cases. +service nginx start + +if [ "${LETS_ENCRYPT_DOMAIN}" != "" -a "${LETS_ENCRYPT_MAIL}" != "" ]; then + if [ ! -f "${SSL_CERTIFICATE_PATH}" -a ! -f "${SSL_KEY_PATH}" ]; then + start_process documentserver-letsencrypt.sh ${LETS_ENCRYPT_MAIL} ${LETS_ENCRYPT_DOMAIN} + fi +fi + +# Regenerate the fonts list and the fonts thumbnails +if [ "${GENERATE_FONTS}" == "true" ]; then + start_process documentserver-generate-allfonts.sh ${ONLYOFFICE_DATA_CONTAINER} +fi + +start_process documentserver-static-gzip.sh ${ONLYOFFICE_DATA_CONTAINER} + +echo "${JWT_MESSAGE}" + +start_process bash -c "find '$DS_LOG_DIR' '$DS_LOG_DIR-example' -type f -name '*.log' | xargs tail -F" \ No newline at end of file diff --git a/setup/templates/php/Dockerfile b/setup/templates/php/Dockerfile index c978dfa5..95cb2f63 100644 --- a/setup/templates/php/Dockerfile +++ b/setup/templates/php/Dockerfile @@ -1,6 +1,6 @@ FROM debian:12 -RUN apt-get update && apt-get install -y vim ca-certificates curl zip unzip git php8.2-cli php8.2-zip php8.2-dom php8.2-mbstring php-json +RUN apt-get update && apt-get install -y vim ca-certificates curl zip unzip git php8.2-curl php8.2-cli php8.2-zip php8.2-dom php8.2-mbstring php-json RUN install -m 0755 -d /etc/apt/keyrings RUN curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc RUN chmod a+r /etc/apt/keyrings/docker.asc diff --git a/setup/templates/proxy/Dockerfile b/setup/templates/proxy/Dockerfile index 141f2d41..160f123a 100755 --- a/setup/templates/proxy/Dockerfile +++ b/setup/templates/proxy/Dockerfile @@ -3,8 +3,10 @@ FROM debian:12 RUN apt-get update && apt-get install -y supervisor RUN apt-get update && apt-get install -y vim nano less virt-what net-tools procps curl +RUN mkdir -m 755 -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN echo "Package: salt-*\nPin: version 3006.22\nPin-Priority: 1001" >> /etc/apt/preferences.d/salt-pin-1001 RUN apt-get update && apt-get install -y salt-minion EXPOSE 80 443 diff --git a/setup/templates/proxy/conf/nginx/local.conf b/setup/templates/proxy/conf/nginx/local.conf index 9e368ac4..74057df3 100755 --- a/setup/templates/proxy/conf/nginx/local.conf +++ b/setup/templates/proxy/conf/nginx/local.conf @@ -62,6 +62,17 @@ server { rewrite ^/keycloak/(.*) /$1 break; } + location /office/ { + proxy_pass http://172.24.0.251/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_pass_request_headers on; + proxy_set_header X-Forwarded-Proto https; + + rewrite ^/office/(.*) /office/$1 break; + } + access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log warn; } diff --git a/setup/templates/salt/Dockerfile b/setup/templates/salt/Dockerfile index c1d40994..08a4c21f 100755 --- a/setup/templates/salt/Dockerfile +++ b/setup/templates/salt/Dockerfile @@ -2,8 +2,10 @@ FROM debian:12 RUN apt-get update && apt-get install -y vim nano less virt-what net-tools procps curl +RUN mkdir -m 755 -p /etc/apt/keyrings RUN curl -fsSL https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public | tee /etc/apt/keyrings/salt-archive-keyring.pgp RUN curl -fsSL https://github.com/saltstack/salt-install-guide/releases/latest/download/salt.sources | tee /etc/apt/sources.list.d/salt.sources +RUN echo "Package: salt-*\nPin: version 3006.22\nPin-Priority: 1001" >> /etc/apt/preferences.d/salt-pin-1001 RUN apt-get update && apt-get install -y salt-master ENTRYPOINT ["salt-master", "-l", "debug"] \ No newline at end of file diff --git a/setup/uninstall.sh b/setup/uninstall.sh index d8082b14..1ef28527 100755 --- a/setup/uninstall.sh +++ b/setup/uninstall.sh @@ -48,6 +48,7 @@ fi if [ -z $1 ] then echo "This will delete all doil related files on your system." + echo "ATTENTION: This will also delete all images with no related container." echo "If you keep instances, you have to relink them after a new doil installation." read -r -p "Do you also want to delete all instances and images? [y/N] " RESPONSE case "$RESPONSE" in diff --git a/setup/updates/update-20260617.sh b/setup/updates/update-20260617.sh index e0c6775f..8c2d4c15 100644 --- a/setup/updates/update-20260617.sh +++ b/setup/updates/update-20260617.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -doil_update_20260617() { +doil_update_20260624() { cp -r ${SCRIPT_DIR}/../app/src/* /usr/local/lib/doil/app/src/ cp -r ${SCRIPT_DIR}/../setup/stack/states/autoinstall/* /usr/local/share/doil/stack/states/autoinstall/ diff --git a/setup/updates/update-20260624.sh b/setup/updates/update-20260624.sh new file mode 100644 index 00000000..ef1f8732 --- /dev/null +++ b/setup/updates/update-20260624.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +doil_update_20260602() { + +cat <&1 > /var/log/doil/stream.log) 2>&1 > /var/log/doil/stream.log + sleep 20 + docker exec -i doil_office bash -c "grep -qxF '172.24.0.254 doil' /etc/hosts || echo '172.24.0.254 doil' >> /etc/hosts" 2>&1 > /var/log/doil/stream.log + fi + + doil salt:restart + + return $? +} \ No newline at end of file diff --git a/setup/updates/update.sh b/setup/updates/update.sh index dc2f6f04..a15cfb70 100755 --- a/setup/updates/update.sh +++ b/setup/updates/update.sh @@ -2,6 +2,7 @@ update() { ENABLE_KEYCLOAK=$(doil_get_conf enable_keycloak) + ENABLE_OFFICE=$(doil_get_conf enable_office) doil_status_send_message_nl "Stopping all services" doil_system_stop_instances @@ -17,7 +18,7 @@ update() { doil_status_send_message "Copying new doil system" doil_system_create_folder - doil_system_copy_doil "$ENABLE_KEYCLOAK" + doil_system_copy_doil "$ENABLE_KEYCLOAK" "$ENABLE_OFFICE" doil_status_okay doil_status_send_message "Creating log file" @@ -52,7 +53,7 @@ update() { doil_status_send_message "Copying new doil system" doil_system_create_folder - doil_system_copy_doil "$ENABLE_KEYCLOAK" + doil_system_copy_doil "$ENABLE_KEYCLOAK" "$ENABLE_OFFICE" doil_status_okay doil_status_send_message "Adding safe git dir for user" @@ -106,5 +107,14 @@ update() { doil_system_install_mailserver doil_status_okay + # start office server + if [[ "$ENABLE_OFFICE" == true ]] + then + doil_status_send_message "Reinstalling office service" + doil_system_install_officeserver + doil_status_okay + fi + + return 0 } \ No newline at end of file