Archived
1
0
Fork 0

Release 2.26 which incorporates the following changes (#1)
Some checks reported errors
continuous-integration/drone/push Build was killed

- Add a ENV_DIR for docker containers to allow changing the env file location changes where the rest of the configuration is bootstrapped from
- Add log_dir and snapshot_dir in env file configuration to determine the log and snapshot directories
- Massively cleaned up README and provide better examples

Co-authored-by: Varakh <varakh@varakh.de>
Reviewed-on: #1
This commit is contained in:
Varakh 2023-04-06 20:55:21 +00:00
parent b61677ebe8
commit 5805279633
15 changed files with 342 additions and 305 deletions

View file

@ -1,5 +1,16 @@
# CHANGELOG # CHANGELOG
## 2.2.6 - 2023/04/06
_Quick update for an outdated application to make it more useful for docker setups. Keep in mind that PHP 7.4 which is used by ts3web is still EOL!_
* Made it possible to use environment variable to define location of bootstrapping `env` file in docker containers (natively, set php-fpm `ENV[]` properly!)
* `ENV_DIR`: location of the **PARENT** folder which has the `env` file inside
* Falls back to application `$appDir/config/env` file if not set
* Added new `env` file variables to easily configure
* `log_dir`: location of the log dir, _without trailing slash_
* `snapshot_dir` location of the snapshots dir, _without trailing slash_
## 2.2.5 - 2022/12/17 ## 2.2.5 - 2022/12/17
* Updated `Dockerfile` (as long as alpine 3.15 shipping PHP7 is kept updated, `ts3web` docker images are kept) * Updated `Dockerfile` (as long as alpine 3.15 shipping PHP7 is kept updated, `ts3web` docker images are kept)
* Updated some symfony dependencies * Updated some symfony dependencies

View file

@ -1,17 +1,12 @@
FROM alpine:3.15 FROM alpine:3.15
LABEL maintainer="Varakh <varakh@varakh.de>" \ LABEL maintainer="Varakh<varakh@varakh.de>"
description="ts3web" \
org.opencontainers.image.authors="Varakh" \
org.opencontainers.image.revision="${REVISION}" \
org.opencontainers.image.vendor="Varakh" \
org.opencontainers.image.title="ts3web" \
org.opencontainers.image.description="ts3web" \
org.opencontainers.image.base.name="alpine:3.15" \
org.opencontainers.artifact.created=${CREATED} \
org.opencontainers.image.source=${SOURCE_URL}
ENV APP_HOME /var/www/html/application ENV APP_HOME=/var/www/html/application \
PHP_MEMORY_LIMIT=512M \
MAX_UPLOAD=1024M \
PHP_MAX_FILE_UPLOAD=200 \
PHP_MAX_POST=1024M
# setup folder structure # setup folder structure
RUN mkdir -p ${APP_HOME}/data/snapshots && \ RUN mkdir -p ${APP_HOME}/data/snapshots && \
@ -19,6 +14,9 @@ RUN mkdir -p ${APP_HOME}/data/snapshots && \
touch ${APP_HOME}/log/application.log && \ touch ${APP_HOME}/log/application.log && \
mkdir -p ${APP_HOME}/config mkdir -p ${APP_HOME}/config
# entrypoint
ADD docker/configure.php /configure.php
# add upstream application # add upstream application
ADD src ${APP_HOME}/src ADD src ${APP_HOME}/src
ADD public ${APP_HOME}/public ADD public ${APP_HOME}/public
@ -26,16 +24,11 @@ ADD composer.json ${APP_HOME}/composer.json
ADD composer.lock ${APP_HOME}/composer.lock ADD composer.lock ${APP_HOME}/composer.lock
ADD data ${APP_HOME}/data ADD data ${APP_HOME}/data
ADD config ${APP_HOME}/config ADD config ${APP_HOME}/config
RUN mv ${APP_HOME}/config/env.example ${APP_HOME}/config/env
# php.ini
ENV PHP_MEMORY_LIMIT=512M \
MAX_UPLOAD=1024M \
PHP_MAX_FILE_UPLOAD=200 \
PHP_MAX_POST=1024M
# install dependencies # install dependencies
RUN apk add --update --no-cache \ RUN cp ${APP_HOME}/config/env.example ${APP_HOME}/config/env && \
apk add --update --no-cache \
bash \
nginx \ nginx \
s6 \ s6 \
curl \ curl \
@ -80,10 +73,13 @@ RUN apk add --update --no-cache \
# Add nginx config # Add nginx config
ADD docker/nginx.conf /etc/nginx/nginx.conf ADD docker/nginx.conf /etc/nginx/nginx.conf
# Add required environment variables to php-fpm
RUN echo "env[ENV_DIR]=%%%ENV_DIR%%%" >> /etc/php7/php-fpm.d/www.conf
EXPOSE 80 EXPOSE 80
# add overlay # add overlay
ADD docker/s6 /etc/s6/ ADD docker/s6 /etc/s6/
# expose start # expose start
CMD exec s6-svscan /etc/s6/ CMD /usr/bin/php /configure.php && exec s6-svscan /etc/s6/

451
README.md
View file

@ -12,29 +12,211 @@ The minimalistic approach of this application is intentional.
There are many TeamSpeak 3 web interfaces out. Why should I pick ts3web? Free, simple, stateless, easy to extend, There are many TeamSpeak 3 web interfaces out. Why should I pick ts3web? Free, simple, stateless, easy to extend,
standard bootstrap theme. standard bootstrap theme.
The main git repository is hosted at _[https://git.myservermanager.com/varakh/ts3web](https://git.myservermanager.com/varakh/ts3web)_. The main git repository is hosted at
_[https://git.myservermanager.com/varakh/ts3web](https://git.myservermanager.com/varakh/ts3web)_.
Other repositories are mirrors and pull requests, issues, and planning are managed there. Other repositories are mirrors and pull requests, issues, and planning are managed there.
Contributions are very welcome! Contributions are very welcome!
## Limitations
TeamSpeak has a detailed interface for permissions and uploading files, therefore the following features are not
supported:
* uploading files (only viewing and deleting, use the official client for uploading)
* editing permissions (only viewing, use the client for editing)
## READ BEFORE USING ## READ BEFORE USING
This web interface makes **heavy use of TeamSpeak 3 server query commands**. Please ensure that you _increase query This web interface makes **heavy use of TeamSpeak 3 server query commands**. Please ensure that you _increase query
limits_ and whitelist the requesting IP address to a `whitelist.txt` when in a docker environment (see below). limits_ and whitelist the requesting IP address to a `whitelist.txt` when in a docker environment (see below).
Please read the next FAQ section carefully! Please read the next sections carefully.
## F.A.Q ## Setup
_ts3web_ can be deployed natively or via docker. It's recommended to use docker with docker-compose. Those steps are
outlined below.
### docker-compose
General remarks:
* By default, `/var/www/html/application/config/env` is used for bootstrapping necessary configuration, can be set to another parent directory with `ENV_DIR` in docker environment variable, e.g., `ENV_DIR=/data`
* By default, `/var/www/html/application/data/snapshots` is used for storing snapshots, path can be changed in the `env` file with `snapshot_dir`
* By default, `/var/www/html/application/log` is used for storing and reading logs, path can be changed in the `env` file with `log_dir`
* Other `env` configuration values are outlined in the [env.example](./config/env.example) file which is also present in the default docker image.
It's recommended to use the `network=HOST` option for the docker setup, and it will be the only example in this `README` file.
Let's create the docker volumes first. You could also use automatically generated ones by the `docker-compose` file, you
would need to remove the `external: true` in the `volumes` section of the `docker-compose.yml` then.
Create the external volumes:
```shell
docker volume create ts3-vol
docker volume create ts3web-vol
```
Paste the example `docker-compose.yml` into a file on your machine:
```yaml
version: '2.1'
networks:
teamspeak:
external: false
services:
app:
container_name: teamspeak_app
image: teamspeak:latest
volumes:
- ts3-vol:/var/ts3server
# ports are all public here in the HOST mode example
environment:
- TS3SERVER_LICENSE=accept
- TS3SERVER_IP_WHITELIST=/var/ts3server/whitelist.txt
restart: unless-stopped
network_mode: "host"
web:
container_name: teamspeak_web
image: varakh/ts3web:latest
volumes:
- ts3web-vol:/data
environment:
# volume needs to contain the env file!
- ENV_DIR=/data
ports:
- 127.0.0.1:8181:80
depends_on:
- app
restart: unless-stopped
networks:
- teamspeak
volumes:
ts3-vol:
ts3web-vol:
```
Let's populate our docker volumes **before** we start!
```shell
docker run -d --rm --name ts3web_creator -v ts3web-vol:/mnt alpine tail -f /dev/null
docker exec -it ts3web_creator sh
# inside the container, edit the env by copying the example to the docker volume mount path at /data/env
cp /var/www/html/application/config/env /data/env
# edit the env file to your liking
#
# the teamspeak_host should point to your public ip address and must be whitelisted inside the teamspeak server itself
vi env
# create necessary directories and set permissions
mkdir -p /data/log
touch /data/log/application.log
mkdir -p /data/snapshots
chown -R 65534:65534 /data
# exit the container
exit
# on the host system, stop the creator container
docker stop ts3web_creator
```
Let's populate the teamspeak container with a proper `whitelist.txt` file. See [ensure that you're whitelisting the IP from which the webinterface will issue commands](#whitelisttextfile).
```shell
docker run -d --rm --name ts3_creator -v ts3-vol:/mnt alpine tail -f /dev/null
docker exec -it ts3_creator sh
# edit the whitelist.txt file at /var/ts3server/whitelist.txt
# it should contain the following entries
#
# 127.0.0.1
# ::1
# your-public-ip
#
vi /var/ts3server/whitelist.txt
# exit the container
exit
# on the host system, stop the creator container
docker stop ts3_creator
```
Maybe you like to copy valid license files into the `ts3-vol` docker volume before stopping.
_Finally_, start the stack with `docker-compose up -d`. Please see the **Reverse proxy** section for a nginx example.
### Reverse proxy
Here's an example on how to configure a reverse proxy for the web interface docker container
```shell
root .../public;
index index.php;
# enable and setup if you have a certificate (highly recommended)
#ssl on;
#ssl_certificate fullchain.pem;
#ssl_certificate_key privkey.pem;
rewrite_log on;
location / {
try_files $uri $uri/ @ee;
}
location @ee {
rewrite ^(.*) /index.php?$1 last;
}
# php fpm
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
include fastcgi_params;
}
```
## Native application
**Prerequisite**: `php`, `composer` and probably `php-fpm` installed on the server.
### Install
* Clone repository
* Change directory to project home
* Execute `composer install`
* `composer install`
* Do the configuration by coping the `env.example` file (see information above)
* Use a web server _or_ run directly via the embedded PHP server: `php -S localhost:8080 -t public public/index.php`.
* Point your browser to [localhost:8080](http://localhost:8080)
* Apply any [whitelist.txt](#whitelist-text-file) changes if you configured `teamspeak_host` differently
than `localhost`
### Upgrade
* Change directory to project home
* `git pull`
* `composer update`
## Troubleshooting / F.A.Q
<a name="flood"></a> <a name="flood"></a>
### How to overcome server query limit? ### How to overcome server query limit?
You might get one of these messages: You might get one of these messages:
> I always get `flood client` message when clicking anywhere in the web interface. > I always get `flood client` message when clicking anywhere in the web interface.
The web UI uses query commands _a lot_! When your instance is up and running, you should be able to change the following The web UI uses query commands _a lot_! When your instance is up and running, you should be able to change the following
setting, e.g. directly in your database (MySQL or sqlite). setting, e.g. directly in your database (MySQL or sqlite).
```ini ```ini
@ -44,193 +226,28 @@ serverinstance_serverquery_flood_time = 1
``` ```
<a name="whitelist"></a> <a name="whitelist"></a>
> I always get `TSException: Error: host isn't a ts3 instance!` when selecting a server. > I always get `TSException: Error: host isn't a ts3 instance!` when selecting a server.
You're probably on a docker environment and the TeamSpeak server is queried through the web UI which You're probably on a docker environment and the TeamSpeak server is queried through the web UI which
resides behind a web server, so the TeamSpeak server thinks that the _remote web server IP address_ invokes the query resides behind a web server, so the TeamSpeak server thinks that the _remote web server IP address_ invokes the query
commands and thus blacklists it. commands and thus blacklists it.
You need define an exception for you server's IP in a [`whitelist.txt` file](#whitelist-text-file) and include it in You need define an exception for you server's IP in a [`whitelist.txt`](#whitelisttextfile) file and include it in
your TeamSpeak application. your TeamSpeak application.
You can also add the desired IP to `query_ip_allowlist.txt` and `query_ip_whitelist.txt` within the TeamSpeak 3 Server You can also add the desired IP to `query_ip_allowlist.txt` and `query_ip_whitelist.txt` within the TeamSpeak 3 Server
data directory (in example it's `./ts3server` where your `docker-compose.yml` resides). data directory.
<a name="dockerperms"></a> <a name="dockerperms"></a>
### I always get `no write permissions` or something similar when trying to save snapshots or when a log entry is created. ### I always get `no write permissions` or something similar when trying to save snapshots or when a log entry is created.
This probably happens when you're in the docker setup. Ensure that host binds have permissions set up properly. The user This probably happens when you're in the docker setup. Ensure that host binds have permissions set up properly and also files inside any
which is used in the docker container is `nobody` with id `65534`. If, e.g. logs are host bound, then execute docker volume has the correct permissions. The user which is used in the docker container is `nobody` with id `65534`.
`chown -R 65534:65534 host/path/to/log`. The same holds true for snapshots.
In the below `docker-compose.yml` file it's advised to execute the following command when you're in the _same_ directory Change owner permissions recursively with `chown -R 65534:65534 /path/to/dir`.
as the `docker-compose.yml` file resides in: `chown -R 65534:65534 env snapshots log`.
## Configuration <a name="whitelisttextfile"></a>
### What's a whitelist.txt and why do I need it?
The main configuration file for the *web interface* is the `env` file located in `config/`. There's an example file
called `env.example` which you **need** to copy to `config/env`. Defaults will assume you're running your TeamSpeak
server on `localhost` with default port. Docker deployments can and *should* host bind this file into the container
directly and just maintain the `env` file.
## Deployment
The application can be deployed two different ways. See below for more information. For each deployment type a running
TeamSpeak 3 instance is a prerequisite.
In the `docker-compose.yml` [example](#docker-compose), a setup together with a teamspeak server instance is shown.
### Docker
**Important. Read before setup!**
- [README](#readme)
- [READ BEFORE USING](#read-before-using)
- [F.A.Q](#faq)
- [How to overcome server query limit?](#how-to-overcome-server-query-limit)
- [I always get `no write permissions` or something similar when trying to save snapshots or when a log entry is created.](#i-always-get-no-write-permissions-or-something-similar-when-trying-to-save-snapshots-or-when-a-log-entry-is-created)
- [Configuration](#configuration)
- [Deployment](#deployment)
- [Docker](#docker)
- [docker standalone](#docker-standalone)
- [docker-compose](#docker-compose)
- [whitelist text file](#whitelist-text-file)
- [As native PHP application](#as-native-php-application)
- [Install:](#install)
- [Upgrade:](#upgrade)
- [Reverse proxy](#reverse-proxy)
- [Limitations](#limitations)
- [Development](#development)
- [Release](#release)
- [Prepare next development cycle](#prepare-next-development-cycle)
- [Helpers](#helpers)
- [Translations](#translations)
- [Theme](#theme)
#### docker standalone
The following section outlines a manual setup. Feel free to use the provided `docker-compose.yml` as quick setup.
1. Create docker volumes for `snapshots`, `log` and `env`. Alternative is to host bind them into your containers.
2. Create a docker network with a fixed IP range or later use host network.
3. Depending on your setup, you need to change `teamspeak_host` of your `env` file to point either to `your IP` or to a
`fixed docker IP` which your teamspeak uses. `localhost` is not valid if you're using it in docker. If you're unsure,
please take a look at the example `docker-compose.yml` files.
4. Start a container using the docker image `varakh/ts3web` and provide the following bindings for volumes:
* `{env_file_volume|host_file}:/var/www/html/applicationconfig/env`
* `{snapshot_volume|host_folder}:/var/www/html/application/data/snapshots`
* `{log_volume|host_folder}:/var/www/html/application/log`
5. [Ensure that you're whitelisting the IP from which the webinterface will issue commands.](#whitelist-text-file)
6. Run the `docker run` command including your settings, volumes and networks (if
any): `docker run --name teamspeak_web -v ./env:/var/www/html/application/config/env -p 8181:80 varakh/ts3web:latest`
.
#### docker-compose
In order for TeamSpeak to show correct IP and country flags, the `network_mode = "host"` is advised. It's also possible
to set everything up without using the host network mode and use fixed IPs.
The examples will use host binds for volumes. Feel free to adapt the `docker-compose.yml` template and use docker
volumes instead if you like.
Ensure to [apply permissions](#i-always-get-no-write-permissions-or-something-similar-when-trying-to-save-snapshots-or-when-a-log-entry-is-created) for volumes though.
<details>
<summary>docker host mode example</summary>
```
version: '2.1'
networks:
teamspeak:
external: false
services:
app:
container_name: teamspeak_app
image: teamspeak:latest
volumes:
- ./ts3server:/var/ts3server
- ./whitelist.txt:/whitelist.txt
ports:
- 10011:10011
- 30033:30033
- 9987:9987/udp
environment:
- TS3SERVER_LICENSE=accept
- TS3SERVER_IP_WHITELIST=/whitelist.txt
restart: always
network_mode: "host"
web:
container_name: teamspeak_web
image: varakh/ts3web:latest
volumes:
- ./env:/var/www/html/application/config/env
- ./snapshots:/var/www/html/application/data/snapshots
- ./log:/var/www/html/application/log
ports:
- 127.0.0.1:8181:80
depends_on:
- app
restart: always
networks:
- teamspeak
```
</details>
<details>
<summary>docker without host mode example</summary>
```
version: '2.1'
networks:
teamspeak:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1
services:
app:
container_name: teamspeak_app
image: teamspeak:latest
volumes:
- ./ts3server:/var/ts3server
- ./whitelist.txt:/whitelist.txt
environment:
- TS3SERVER_LICENSE=accept
- TS3SERVER_IP_WHITELIST=/whitelist.txt
restart: always
ports:
- 10011:10011
- 30033:30033
- 9987:9987/udp
networks:
teamspeak:
ipv4_address: 10.5.0.5
web:
container_name: teamspeak_web
image: varakh/ts3web:latest
volumes:
- ./env:/var/www/html/application/config/env
- ./snapshots:/var/www/html/application/data/snapshots
- ./log:/var/www/html/application/log
ports:
- 127.0.0.1:8181:80
depends_on:
- app
restart: always
networks:
teamspeak:
ipv4_address: 10.5.0.6
```
</details>
#### whitelist text file
The following illustrates a valid `whitelist.txt` file which can be used for the above `docker-compose` setups. You need The following illustrates a valid `whitelist.txt` file which can be used for the above `docker-compose` setups. You need
to replace `your-public-ip` with the TeamSpeak's public IP address if required or remove the fixed internal docker IP if to replace `your-public-ip` with the TeamSpeak's public IP address if required or remove the fixed internal docker IP if
@ -243,81 +260,9 @@ you're on 'host' mode.
your-public-ip your-public-ip
``` ```
Now execute `docker-compose up -d` to start those containers. If you like to update, do `docker-compose down`,
`docker-compose pull` and then `docker-compose up -d` again.
Your TeamSpeak 3 Server will be available under `public-server-ip:9987`. The web interface will be available on
`127.0.0.1:8181`. You need to add a [reverse proxy](#reverseproxy) and probably you also want SSL configured if you
expose it via domain. For testing purposes, change `- 127.0.0.1:8181:80` to `- 8181:80`. The web interface will then be
available under
`public-server-ip:8181`.
This is **not recommended**! Secure your setup properly via [reverse proxy and SSL](#reverse-proxy).
### As native PHP application
**Prerequisite**: `php`, `composer` and probably `php-fpm` installed on the server.
#### Install:
* Clone repository
* Change directory to project home
* Execute `composer install`
* `composer install`
* Do the configuration by coping the `env.example` file (see information above)
* Use a web server _or_ run directly via the embedded PHP server: `php -S localhost:8080 -t public public/index.php`.
* Point your browser to [localhost:8080](http://localhost:8080)
* Apply any [whitelist.txt](#whitelist-text-file) changes if you configured `teamspeak_host` differently
than `localhost`
#### Upgrade:
* Change directory to project home
* `git pull`
* `composer update`
### Reverse proxy
Here's an example on how to configure a reverse proxy for the web interface docker container
```
root .../public;
index index.php;
# enable and setup if you have a certificate (highly recommended)
#ssl on;
#ssl_certificate fullchain.pem;
#ssl_certificate_key privkey.pem;
rewrite_log on;
location / {
try_files $uri $uri/ @ee;
}
location @ee {
rewrite ^(.*) /index.php?$1 last;
}
# php fpm
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
include fastcgi_params;
}
```
## Limitations
TeamSpeak has a detailed interface for permissions and uploading files, therefore the following features are not
supported:
* uploading files (only viewing and deleting, use the official client for uploading)
* editing permissions (only viewing, use the client for editing)
## Development ## Development
If you're willing to contribute, here's some information. Contributions are welcome!
### Release ### Release

View file

@ -13,7 +13,7 @@ class Constants
/** /**
* Version tag * Version tag
*/ */
const VERSION = '2.2.5'; const VERSION = '2.2.6';
/** /**
* Return constant by its class name * Return constant by its class name

View file

@ -8,12 +8,27 @@ class EnvConstants
/** /**
* Example env file * Example env file
*/ */
const ENV_FILE_EXAMPLE = "env.example"; const FILE_NAME_EXAMPLE_ENV = "env.example";
/** /**
* Custom env file * Custom env file
*/ */
const ENV_FILE = "env"; const FILE_NAME_ENV = "env";
/**
* The path to the env file
*/
const ENV_DIR = "ENV_DIR";
/**
* The path to the logs directory
*/
const LOG_DIR = "log_dir";
/**
* The path to the snapshots directory
*/
const SNAPSHOT_DIR = "snapshot_dir";
/** /**
* Site title * Site title
@ -31,7 +46,7 @@ class EnvConstants
const SITE_DATE_FORMAT = "site_date_format"; const SITE_DATE_FORMAT = "site_date_format";
/** /**
* THeme * Theme
*/ */
const THEME = "theme"; const THEME = "theme";
@ -86,4 +101,4 @@ class EnvConstants
EnvConstants::LOG_NAME, EnvConstants::LOG_NAME,
EnvConstants::LOG_LEVEL EnvConstants::LOG_LEVEL
]; ];
} }

View file

@ -8,12 +8,16 @@ theme="bootstrap4" # values: bootstrap4 (foldernames are used to determine theme
theme_cache=false # values: true|false (cache view/twig. makes it faster, disable for debug) theme_cache=false # values: true|false (cache view/twig. makes it faster, disable for debug)
# teamspeak # teamspeak
teamspeak_host="localhost" # 'localhost' or 'name_of_docker_container' if running locally teamspeak_host="app" # 'localhost' or 'name_of_docker_container|name_of_the_docker-compose_service' if running locally
teamspeak_query_port=10011 teamspeak_query_port=10011
teamspeak_user="serveradmin" teamspeak_user="serveradmin"
teamspeak_tree_view="true" # show a tree view in the details of online clients if a server has been selected teamspeak_tree_view="true" # show a tree view in the details of online clients if a server has been selected
teamspeak_log_lines=100 # show this amount of latest log lines teamspeak_log_lines=100 # show this amount of latest log lines
# log # log
log_dir=/var/www/html/application/log
log_name="ts3web" # values: all strings log_name="ts3web" # values: all strings
log_level="INFO" # values: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY log_level="INFO" # values: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY
# snapshots
snapshot_dir=/var/www/html/application/data/snapshots

22
docker/configure.php Normal file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
echo "Adapting ENV_DIR..." . PHP_EOL;
$path = '/etc/php7/php-fpm.d/www.conf';
$env = "ENV_DIR";
$fileContent = file_get_contents($path);
$fileContent = preg_replace("/%%%" . strtoupper($env) . "%%%/", env($env, "/var/www/html/application/config"), $fileContent);
file_put_contents($path, $fileContent);
function env($name, $default = null)
{
$v = getenv($name) ?: $default;
if ($v === null) {
return "''";
}
return "'" . $v . "'";
}

View file

@ -64,6 +64,7 @@ Carbon::setToStringFormat(getenv(EnvConstants::SITE_DATE_FORMAT));
// logger // logger
try { try {
$logger = BootstrapHelper::bootLogger(); $logger = BootstrapHelper::bootLogger();
$logger->info("Starting ts3web version " . Constants::VERSION);
$container['logger'] = function () use ($logger) { $container['logger'] = function () use ($logger) {
return $logger; return $logger;

View file

@ -19,7 +19,7 @@ final class SnapshotCreateAction extends AbstractAction
$fileSystem = new Filesystem(); $fileSystem = new Filesystem();
$name = Carbon::now()->getTimestamp(); $name = Carbon::now()->getTimestamp();
$path = FileHelper::SNAPSHOTS_PATH . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name; $path = FileHelper::getSnapshotsDir() . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name;
if ($fileSystem->exists($path)) { if ($fileSystem->exists($path)) {
$this->flash->addMessage('error', $this->translator->trans('file.exists')); $this->flash->addMessage('error', $this->translator->trans('file.exists'));
@ -35,4 +35,4 @@ final class SnapshotCreateAction extends AbstractAction
return $response->withRedirect('/snapshots/' . $sid); return $response->withRedirect('/snapshots/' . $sid);
} }
} }

View file

@ -16,14 +16,14 @@ final class SnapshotDeleteAction extends AbstractAction
$this->ts->getInstance()->selectServer($sid, 'serverId'); $this->ts->getInstance()->selectServer($sid, 'serverId');
$fileSystem = new Filesystem(); $fileSystem = new Filesystem();
$path = FileHelper::SNAPSHOTS_PATH . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name; $path = FileHelper::getSnapshotsDir() . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name;
if (!$fileSystem->exists($path)) { if (!$fileSystem->exists($path)) {
$this->flash->addMessage('error', $this->translator->trans('file.notexists')); $this->flash->addMessage('error', $this->translator->trans('file.notexists'));
} else { } else {
try { try {
$fileSystem->remove($path); $fileSystem->remove($path);
$serverPath = FileHelper::SNAPSHOTS_PATH . DIRECTORY_SEPARATOR . $sid; $serverPath = FileHelper::getSnapshotsDir() . DIRECTORY_SEPARATOR . $sid;
if (count(FileHelper::getFiles($serverPath)) == 0) { if (count(FileHelper::getFiles($serverPath)) == 0) {
$fileSystem->remove($serverPath); $fileSystem->remove($serverPath);

View file

@ -15,7 +15,7 @@ final class SnapshotDeployAction extends AbstractAction
$this->ts->getInstance()->selectServer($sid, 'serverId'); $this->ts->getInstance()->selectServer($sid, 'serverId');
$fileSystem = new Filesystem(); $fileSystem = new Filesystem();
$path = FileHelper::SNAPSHOTS_PATH . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name; $path = FileHelper::getSnapshotsDir() . DIRECTORY_SEPARATOR . $sid . DIRECTORY_SEPARATOR . $name;
if (!$fileSystem->exists($path)) { if (!$fileSystem->exists($path)) {
$this->flash->addMessage('error', $this->translator->trans('file.notexists')); $this->flash->addMessage('error', $this->translator->trans('file.notexists'));
@ -32,4 +32,4 @@ final class SnapshotDeployAction extends AbstractAction
return $response->withRedirect('/snapshots/' . $sid); return $response->withRedirect('/snapshots/' . $sid);
} }
} }

View file

@ -12,7 +12,7 @@ final class SnapshotsAction extends AbstractAction
$this->ts->login($this->auth->getIdentity()['user'], $this->auth->getIdentity()['password']); $this->ts->login($this->auth->getIdentity()['user'], $this->auth->getIdentity()['password']);
$this->ts->getInstance()->selectServer($sid, 'serverId'); $this->ts->getInstance()->selectServer($sid, 'serverId');
$snapshots = FileHelper::getFiles(FileHelper::SNAPSHOTS_PATH . DIRECTORY_SEPARATOR . $sid); $snapshots = FileHelper::getFiles(FileHelper::getSnapshotsDir() . DIRECTORY_SEPARATOR . $sid);
$this->view->render($response, 'snapshots.twig', [ $this->view->render($response, 'snapshots.twig', [
'title' => $this->translator->trans('snapshots.title'), 'title' => $this->translator->trans('snapshots.title'),
@ -20,4 +20,4 @@ final class SnapshotsAction extends AbstractAction
'sid' => $sid 'sid' => $sid
]); ]);
} }
} }

View file

@ -22,20 +22,39 @@ class BootstrapHelper
*/ */
public static function bootEnvironment() public static function bootEnvironment()
{ {
$envPath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'config'; $envDir = getenv(EnvConstants::ENV_DIR, true);
$envFileExample = $envPath . DIRECTORY_SEPARATOR . EnvConstants::ENV_FILE_EXAMPLE; $externalEnvDir = true;
$envFile = $envPath . DIRECTORY_SEPARATOR . EnvConstants::ENV_FILE;
try { if ($envDir === false) {
$fileSystem = new Filesystem(); $envDir = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'config';
if (!$fileSystem->exists($envFile)) { $externalEnvDir = false;
$fileSystem->copy($envFileExample, $envFile);
}
} catch (IOException $e) {
die('Could not copy example env file ' . $envFileExample . ' to ' . $envFile);
} }
$env = new Dotenv($envPath, EnvConstants::ENV_FILE); $envFile = $envDir . DIRECTORY_SEPARATOR . EnvConstants::FILE_NAME_ENV;
if ($externalEnvDir === false) {
$envFileFallback = $envDir . DIRECTORY_SEPARATOR . EnvConstants::FILE_NAME_EXAMPLE_ENV;
try {
$fileSystem = new Filesystem();
if (!$fileSystem->exists($envFile)) {
$fileSystem->copy($envFileFallback, $envFile);
}
} catch (IOException $e) {
die('Could not copy example env file ' . $envFileFallback . ' to ' . $envFile);
}
} else {
try {
$fileSystem = new Filesystem();
if (!$fileSystem->exists($envFile)) {
die('env file ' . $envFile . ' does not exist');
}
} catch (IOException $e) {
die('Could determine env file ' . $envFile);
}
}
$env = new Dotenv($envDir, EnvConstants::FILE_NAME_ENV);
$res = $env->load(); $res = $env->load();
try { try {
@ -142,7 +161,13 @@ class BootstrapHelper
*/ */
public static function getLogDir() public static function getLogDir()
{ {
return __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'log'; $logDir = getenv(EnvConstants::LOG_DIR);
if ($logDir === false) {
return __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'log';
}
return $logDir;
} }
/** /**
@ -154,4 +179,4 @@ class BootstrapHelper
{ {
return self::getLogDir() . DIRECTORY_SEPARATOR . 'application.log'; return self::getLogDir() . DIRECTORY_SEPARATOR . 'application.log';
} }
} }

View file

@ -1,15 +1,31 @@
<?php <?php
use Carbon\Carbon; use Carbon\Carbon;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
class FileHelper class FileHelper
{ {
const SNAPSHOTS_PATH = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'snapshots'; private const SNAPSHOTS_PATH = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'snapshots';
/** /**
* Get all files in FILES_DIR * Constructs the snapshots directory
* @return string
*/
public static function getSnapshotsDir(): string
{
$snapshotDir = getenv(EnvConstants::SNAPSHOT_DIR);
if ($snapshotDir === false) {
return FileHelper::SNAPSHOTS_PATH;
}
return $snapshotDir;
}
/**
* Get all files in a directory
* *
* @param $directory * @param $directory
* @return array * @return array
@ -38,7 +54,7 @@ class FileHelper
} }
/** /**
* Output human readable file size * Output human-readable file size
* *
* @param $bytes * @param $bytes
* @param int $decimals * @param int $decimals
@ -52,7 +68,7 @@ class FileHelper
} }
/** /**
* Output human readable bandwidth size * Output human-readable bandwidth size
* *
* @param $bytes * @param $bytes
* @param int $decimals * @param int $decimals

View file

@ -38,6 +38,8 @@ class TSInstance
$this->host = getenv(EnvConstants::TEAMSPEAK_HOST); $this->host = getenv(EnvConstants::TEAMSPEAK_HOST);
$this->queryPort = getenv(EnvConstants::TEAMSPEAK_QUERY_PORT); $this->queryPort = getenv(EnvConstants::TEAMSPEAK_QUERY_PORT);
$this->logger->debug(sprintf('Trying to connect to to %s:%s', $this->host, $this->queryPort));
$ts = new ts3admin($this->host, $this->queryPort); $ts = new ts3admin($this->host, $this->queryPort);
$ts = new TS3AdminProxy($ts, $logger); $ts = new TS3AdminProxy($ts, $logger);