first commit
This commit is contained in:
parent
143fd37cfb
commit
5df32939a6
54
Dockerfile
Normal file
54
Dockerfile
Normal file
@ -0,0 +1,54 @@
|
||||
FROM debian:jessie
|
||||
MAINTAINER "Andrey Arapov <andrey.arapov@nixaid.com>"
|
||||
|
||||
# To avoid problems with Dialog and curses wizards
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# OS & Python env deps for taiga-back
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y -- build-essential binutils-doc autoconf flex \
|
||||
bison libjpeg-dev libfreetype6-dev zlib1g-dev libzmq3-dev \
|
||||
libgdbm-dev libncurses5-dev automake libtool libffi-dev curl git \
|
||||
tmux gettext python3.4 python3.4-dev python3-pip libxml2-dev \
|
||||
libxslt-dev libpq-dev virtualenv \
|
||||
nginx \
|
||||
&& rm -rf -- /var/lib/apt/lists/*
|
||||
|
||||
RUN pip3 install circus gunicorn
|
||||
|
||||
# Create taiga user
|
||||
ENV USER taiga
|
||||
ENV UID 1000
|
||||
ENV GROUP www-data
|
||||
ENV HOME /home/$USER
|
||||
ENV DATA /usr/local/taiga
|
||||
RUN useradd -u $UID -m -d $HOME -s /usr/sbin/nologin -g $GROUP $USER
|
||||
RUN mkdir -p $DATA $DATA/media $DATA/static $DATA/logs /var/log/taiga \
|
||||
&& chown -Rh $USER:$GROUP $DATA /var/log/taiga
|
||||
|
||||
# Install taiga-back
|
||||
USER $USER
|
||||
WORKDIR $DATA
|
||||
RUN git clone -b stable https://github.com/taigaio/taiga-back.git $DATA/taiga-back \
|
||||
&& virtualenv -p /usr/bin/python3.4 venvtaiga \
|
||||
&& . venvtaiga/bin/activate \
|
||||
&& cd $DATA/taiga-back \
|
||||
&& pip3 install -r requirements.txt \
|
||||
&& deactivate
|
||||
|
||||
# Install taiga-front (compiled)
|
||||
RUN git clone -b stable https://github.com/taigaio/taiga-front-dist.git $DATA/taiga-front-dist
|
||||
|
||||
USER root
|
||||
|
||||
# Cleanups
|
||||
RUN rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
# Copy template seeds
|
||||
COPY seeds/*.tmpl /tmp/
|
||||
|
||||
VOLUME [ "$DATA/static", \
|
||||
"$DATA/media" ]
|
||||
|
||||
COPY launch /
|
||||
CMD /launch
|
200
README.md
Normal file
200
README.md
Normal file
@ -0,0 +1,200 @@
|
||||
Taiga in Docker
|
||||
===============
|
||||
|
||||
This container allows you to run [Taiga](https://taiga.io/) in a Docker
|
||||
container.
|
||||
|
||||
What is Taiga?
|
||||
--------------
|
||||
|
||||
Taiga is a project management application that can handle both simple and
|
||||
complex projects for startups, software developers, and other target teams.
|
||||
It tracks the progress of a project. Taiga's design is clean and elegant
|
||||
design—something that is supposed to be "beautiful to look at all day long."
|
||||
With Taiga, you can use either Kanban or Scrum template, or both. Backlogs are
|
||||
shown as a running list of all features and User Stories added to the project.
|
||||
|
||||
Taiga integrates video conferencing functions with the use of third party
|
||||
services from Talky.io and Appear.in. Group and private chat is done via HipChat.
|
||||
|
||||
Dockerfile
|
||||
----------
|
||||
|
||||
The Dockerfile performs the following steps:
|
||||
* install the OS & Python dependencies required to run Taiga Django backend.
|
||||
* install nginx - to serve the content including static assests which Django
|
||||
app should not be handling.
|
||||
* install circus - a process & socket manager for the Python web application.
|
||||
* install gunicorn - a Python Web Server Gateway Interface (WSGI) HTTP Server
|
||||
to serve dynamic content.
|
||||
* create taiga user for running circus & gunicorn.
|
||||
* clone stable branches of the taiga backend and frontend.
|
||||
* copy templates which will be then processed by the launch script when the
|
||||
container starts.
|
||||
|
||||
|
||||
Running Taiga
|
||||
=============
|
||||
|
||||
I recommend to use Docker Compose for running the Taiga.
|
||||
|
||||
Docker Compose
|
||||
--------------
|
||||
|
||||
Below is a docker compose file as example
|
||||
|
||||
docker-compose.yml
|
||||
```
|
||||
version: '2'
|
||||
|
||||
volumes:
|
||||
postgres_data: {}
|
||||
taiga_postgres: {}
|
||||
taiga_static: {}
|
||||
taiga_media: {}
|
||||
|
||||
networks:
|
||||
backend: {}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
# https://hub.docker.com/_/postgres/
|
||||
image: postgres
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./db:/docker-entrypoint-initdb.d:ro
|
||||
env_file:
|
||||
- ./postgres.env
|
||||
- ./taiga-db.env
|
||||
|
||||
taiga:
|
||||
# https://hub.docker.com/r/andrey01/taiga
|
||||
image: andrey01/taiga
|
||||
# build: .
|
||||
networks:
|
||||
- backend
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- taiga_static:/usr/local/taiga/static
|
||||
- taiga_media:/usr/local/taiga/media
|
||||
env_file:
|
||||
- ./taiga.env
|
||||
- ./taiga-db.env
|
||||
environment:
|
||||
- TZ=Europe/Amsterdam
|
||||
depends_on:
|
||||
- postgres
|
||||
```
|
||||
|
||||
The following file is required so that Postgres will create taiga database that
|
||||
is used by the Taiga backend.
|
||||
|
||||
db/init-taiga-db.sh
|
||||
```
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
|
||||
CREATE USER $TAIGA_DB_USER;
|
||||
CREATE DATABASE $TAIGA_DB_NAME;
|
||||
GRANT ALL PRIVILEGES ON DATABASE $TAIGA_DB_NAME TO $TAIGA_DB_USER;
|
||||
ALTER USER $TAIGA_DB_USER WITH PASSWORD '$TAIGA_DB_PASSWORD';
|
||||
EOSQL
|
||||
```
|
||||
|
||||
The environment variables
|
||||
-------------------------
|
||||
|
||||
This file will defines a superuser for Postgres.
|
||||
|
||||
postgres.env
|
||||
```
|
||||
POSTGRES_USER=admin
|
||||
POSTGRES_PASSWORD=admin
|
||||
```
|
||||
|
||||
This file defines individual settings for Taiga.
|
||||
|
||||
taiga.env
|
||||
```
|
||||
GUNICORN_WORKERS=1
|
||||
SITE_URI=http://taiga.mydomain.com
|
||||
PUBLIC_REGISTER=true
|
||||
ADMIN_EMAIL=admin@mydomain.com
|
||||
NOREPLY_EMAIL=no-reply@mydomain.com
|
||||
```
|
||||
|
||||
This file defines the database settings for Taiga.
|
||||
|
||||
taiga-db.env
|
||||
```
|
||||
TAIGA_DB_USER=taiga
|
||||
TAIGA_DB_NAME=taiga
|
||||
TAIGA_DB_PASSWORD=secretpassword
|
||||
TAIGA_DB_HOST=postgres
|
||||
TAIGA_DB_PORT=5432
|
||||
```
|
||||
|
||||
Run the Taiga
|
||||
```
|
||||
docker-compose up -d taiga
|
||||
```
|
||||
|
||||
Now you can access Taiga with your favorite Web Browser.
|
||||
|
||||
I recommend to run nginx reverse proxy in front of this container, so that
|
||||
you could use TLS.
|
||||
[Let's Encrypt](https://letsencrypt.org) project is now able to issue free
|
||||
SSL/TLS certificates.
|
||||
|
||||
|
||||
Maintenance
|
||||
===========
|
||||
|
||||
Accessing the Taiga Database
|
||||
----------------------------
|
||||
|
||||
You can access it using the docker compose or docker as follows
|
||||
|
||||
```
|
||||
docker-compose run --rm postgres sh -c 'PGPASSWORD=$TAIGA_DB_PASSWORD exec psql -h "$TAIGA_DB_HOST" -U $TAIGA_DB_USER'
|
||||
```
|
||||
|
||||
```
|
||||
docker run -ti --rm --net taiga_backend --env-file taiga-db.env postgres sh -c 'PGPASSWORD=$TAIGA_DB_PASSWORD exec psql -h "$TAIGA_DB_HOST" -U $TAIGA_DB_USER'
|
||||
```
|
||||
|
||||
Backup the database
|
||||
-------------------
|
||||
|
||||
Below is an example of how you can make the Taiga PostgreSQL database backup
|
||||
```
|
||||
docker-compose run --rm postgres sh -c 'PGPASSWORD=$TAIGA_DB_PASSWORD exec pg_dump -h "$TAIGA_DB_HOST" -U $TAIGA_DB_USER $TAIGA_DB_NAME' > taiga-db.backup
|
||||
```
|
||||
|
||||
To restore it
|
||||
```
|
||||
docker-compose run --rm postgres sh -c 'PGPASSWORD=$TAIGA_DB_PASSWORD exec psql -h "$TAIGA_DB_HOST" -U $TAIGA_DB_USER $TAIGA_DB_NAME' < taiga-db.backup
|
||||
```
|
||||
|
||||
There are also volumes containing the data you might want to backup externally
|
||||
```
|
||||
$ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
local taiga_taiga_postgres
|
||||
local taiga_taiga_media
|
||||
local taiga_taiga_static
|
||||
local taiga_postgres_data
|
||||
```
|
||||
|
||||
|
||||
Useful links
|
||||
------------
|
||||
|
||||
* [Docker Compose file reference](https://docs.docker.com/compose/compose-file/)
|
||||
* [Taiga: Setup production environment](https://taigaio.github.io/taiga-doc/dist/setup-production.html)
|
||||
* [Read Taiga upgrade notes](https://taigaio.github.io/taiga-doc/dist/upgrades.html)
|
||||
* [How to upgrade Taiga](https://taigaio.github.io/taiga-doc/dist/upgrades.html)
|
8
TODO.md
Normal file
8
TODO.md
Normal file
@ -0,0 +1,8 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
* make sure Taiga sends emails, e.g. new user registered, password reset,
|
||||
general Taiga notifications
|
||||
|
||||
* enable Async tasks (leverage RabbitMQ, redis and the Taiga-events websocket
|
||||
server)
|
9
db/init-taiga-db.sh
Executable file
9
db/init-taiga-db.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
|
||||
CREATE USER $TAIGA_DB_USER;
|
||||
CREATE DATABASE $TAIGA_DB_NAME;
|
||||
GRANT ALL PRIVILEGES ON DATABASE $TAIGA_DB_NAME TO $TAIGA_DB_USER;
|
||||
ALTER USER $TAIGA_DB_USER WITH PASSWORD '$TAIGA_DB_PASSWORD';
|
||||
EOSQL
|
42
docker-compose.yml
Normal file
42
docker-compose.yml
Normal file
@ -0,0 +1,42 @@
|
||||
version: '2'
|
||||
|
||||
volumes:
|
||||
postgres_data: {}
|
||||
taiga_postgres: {}
|
||||
taiga_static: {}
|
||||
taiga_media: {}
|
||||
|
||||
networks:
|
||||
backend: {}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
# https://hub.docker.com/_/postgres/
|
||||
image: postgres
|
||||
networks:
|
||||
- backend
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./db:/docker-entrypoint-initdb.d:ro
|
||||
env_file:
|
||||
- ./postgres.env
|
||||
- ./taiga-db.env
|
||||
|
||||
taiga:
|
||||
# https://hub.docker.com/r/andrey01/taiga
|
||||
image: andrey01/taiga
|
||||
# build: .
|
||||
networks:
|
||||
- backend
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- taiga_static:/usr/local/taiga/static
|
||||
- taiga_media:/usr/local/taiga/media
|
||||
env_file:
|
||||
- ./taiga.env
|
||||
- ./taiga-db.env
|
||||
environment:
|
||||
- TZ=Europe/Amsterdam
|
||||
depends_on:
|
||||
- postgres
|
65
launch
Executable file
65
launch
Executable file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Debug
|
||||
# set -x
|
||||
|
||||
# Do Not Change these variables unless you know what you are doing
|
||||
export ESC=$
|
||||
export DJANGO_SECRET_KEY=$(openssl rand -hex 32)
|
||||
|
||||
# Default variables. These shall be overridden :-)
|
||||
export GUNICORN_WORKERS=${GUNICORN_WORKERS:-1}
|
||||
export SITE_URI=${SITE_URI:-http://example.com}
|
||||
export SITE_FQDN=$(echo $SITE_URI | sed -e "s/[^/]*\/\/\([^@]*@\)\?\([^:/]*\).*/\2/")
|
||||
[ "${SITE_URI::5}" == "https" ] && SITE_SCHEME="https" || SITE_SCHEME="http"
|
||||
export SITE_SCHEME
|
||||
[ ${PUBLIC_REGISTER,,} == "false" ] \
|
||||
&& { PUBLIC_REGISTER="False"; PUBLIC_REGISTER_JS="false"; } \
|
||||
|| { PUBLIC_REGISTER="True"; PUBLIC_REGISTER_JS="true"; }
|
||||
export PUBLIC_REGISTER PUBLIC_REGISTER_JS
|
||||
export ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
|
||||
export NOREPLY_EMAIL=${NOREPLY_EMAIL:-no-reply@example.com}
|
||||
export TAIGA_DB_HOST=${TAIGA_DB_HOST:-postgres}
|
||||
export TAIGA_DB_PORT=${TAIGA_DB_PORT:-5432}
|
||||
export TAIGA_DB_NAME=${TAIGA_DB_NAME:-taiga}
|
||||
export TAIGA_DB_USER=${TAIGA_DB_USER:-taiga}
|
||||
export TAIGA_DB_PASSWORD=${TAIGA_DB_PASSWORD:-mysecretpassword}
|
||||
|
||||
# Generate configs based on the template seeds
|
||||
envsubst < /tmp/taiga.tmpl > /etc/nginx/sites-enabled/taiga
|
||||
envsubst < /tmp/circus.ini.tmpl > $DATA/circus.ini
|
||||
envsubst < /tmp/conf.json.tmpl > $DATA/taiga-front-dist/dist/conf.json
|
||||
envsubst < /tmp/local.py.tmpl > $DATA/taiga-back/settings/local.py
|
||||
|
||||
# Keep sensitive information out of here
|
||||
unset DJANGO_SECRET_KEY TAIGA_DB_PASSWORD
|
||||
|
||||
# Make sure the data is readable
|
||||
chown -Rh $USER:$GROUP $DATA
|
||||
|
||||
# Allow a little delay on the first run
|
||||
# to make sure Database is set and ready
|
||||
[ -e "/tmp/taiga.firstrun" ] || ( sleep 5; touch /tmp/taiga.firstrun )
|
||||
|
||||
# Upgrade DB schemas, etc...
|
||||
# This is important when Taiga's codebase gets updated
|
||||
su -s /bin/sh $USER -c '. $DATA/venvtaiga/bin/activate
|
||||
cd $DATA/taiga-back
|
||||
python3 manage.py migrate --noinput
|
||||
python3 manage.py compilemessages
|
||||
python3 manage.py collectstatic --noinput
|
||||
deactivate'
|
||||
|
||||
# (Optional) Create a new user admin with password 123123 and
|
||||
# fill Taiga with the Sample data
|
||||
# su -s /bin/sh $USER -c '. $DATA/venvtaiga/bin/activate
|
||||
# cd $DATA/taiga-back
|
||||
# python3 manage.py loaddata initial_user
|
||||
# python3 manage.py loaddata initial_project_templates
|
||||
# python3 manage.py loaddata initial_role
|
||||
# python3 manage.py sample_data
|
||||
# deactivate'
|
||||
|
||||
# Launch the backend
|
||||
service nginx start
|
||||
su -s /bin/sh $USER -c '/usr/local/bin/circusd "$DATA/circus.ini"'
|
2
postgres.env
Normal file
2
postgres.env
Normal file
@ -0,0 +1,2 @@
|
||||
POSTGRES_USER=admin
|
||||
POSTGRES_PASSWORD=admin
|
31
seeds/circus.ini.tmpl
Normal file
31
seeds/circus.ini.tmpl
Normal file
@ -0,0 +1,31 @@
|
||||
[circus]
|
||||
check_delay = 5
|
||||
endpoint = tcp://127.0.0.1:5555
|
||||
pubsub_endpoint = tcp://127.0.0.1:5556
|
||||
statsd = true
|
||||
|
||||
[watcher:taiga]
|
||||
working_dir = ${DATA}/taiga-back
|
||||
cmd = gunicorn
|
||||
args = -w ${GUNICORN_WORKERS} -t 60 --pythonpath=. -b 127.0.0.1:8001 taiga.wsgi
|
||||
uid = taiga
|
||||
numprocesses = 1
|
||||
autostart = true
|
||||
send_hup = true
|
||||
stdout_stream.class = FileStream
|
||||
stdout_stream.filename = /var/log/taiga/gunicorn.stdout.log
|
||||
stdout_stream.max_bytes = 10485760
|
||||
stdout_stream.backup_count = 4
|
||||
stderr_stream.class = FileStream
|
||||
stderr_stream.filename = /var/log/taiga/gunicorn.stderr.log
|
||||
stderr_stream.max_bytes = 10485760
|
||||
stderr_stream.backup_count = 4
|
||||
|
||||
[env:taiga]
|
||||
PATH = ${DATA}/venvtaiga/bin:${ESC}PATH
|
||||
TERM=rxvt-256color
|
||||
SHELL=/bin/bash
|
||||
USER=taiga
|
||||
LANG=en_US.UTF-8
|
||||
HOME=${DATA}
|
||||
PYTHONPATH=${DATA}/venvtaiga/lib/python3.4/site-packages
|
17
seeds/conf.json.tmpl
Normal file
17
seeds/conf.json.tmpl
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"api": "${SITE_URI}/api/v1/",
|
||||
"eventsUrl": null,
|
||||
"eventsMaxMissedHeartbeats": 5,
|
||||
"eventsHeartbeatIntervalTime": 60000,
|
||||
"debug": true,
|
||||
"debugInfo": false,
|
||||
"defaultLanguage": "en",
|
||||
"themes": ["taiga"],
|
||||
"defaultTheme": "taiga",
|
||||
"publicRegisterEnabled": ${PUBLIC_REGISTER_JS},
|
||||
"feedbackEnabled": true,
|
||||
"privacyPolicyUrl": null,
|
||||
"termsOfServiceUrl": null,
|
||||
"maxUploadFileSize": null,
|
||||
"contribPlugins": []
|
||||
}
|
42
seeds/local.py.tmpl
Normal file
42
seeds/local.py.tmpl
Normal file
@ -0,0 +1,42 @@
|
||||
from .common import *
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': '${TAIGA_DB_NAME}',
|
||||
'USER': '${TAIGA_DB_USER}',
|
||||
'PASSWORD': '${TAIGA_DB_PASSWORD}',
|
||||
'HOST': '${TAIGA_DB_HOST}',
|
||||
'PORT': '${TAIGA_DB_PORT}',
|
||||
}
|
||||
}
|
||||
|
||||
ADMINS = (
|
||||
("Admin", "${ADMIN_EMAIL}"),
|
||||
)
|
||||
|
||||
# THROTTLING (Anti-flood)
|
||||
REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"] = {
|
||||
"anon": "20/min",
|
||||
"user": "200/min",
|
||||
"import-mode": "20/sec",
|
||||
"import-dump-mode": "10/minute"
|
||||
}
|
||||
|
||||
SECRET_KEY = "${DJANGO_SECRET_KEY}"
|
||||
|
||||
MEDIA_ROOT = '${DATA}/media'
|
||||
STATIC_ROOT = '${DATA}/static'
|
||||
|
||||
MEDIA_URL = "${SITE_URI}/media/"
|
||||
STATIC_URL = "${SITE_URI}/static/"
|
||||
ADMIN_MEDIA_PREFIX = "${SITE_URI}/static/admin/"
|
||||
SITES["front"]["scheme"] = "${SITE_SCHEME}"
|
||||
SITES["front"]["domain"] = "${SITE_FQDN}"
|
||||
|
||||
DEBUG = False
|
||||
TEMPLATE_DEBUG = False
|
||||
PUBLIC_REGISTER_ENABLED = ${PUBLIC_REGISTER}
|
||||
|
||||
DEFAULT_FROM_EMAIL = "${NOREPLY_EMAIL}"
|
||||
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
49
seeds/taiga.tmpl
Normal file
49
seeds/taiga.tmpl
Normal file
@ -0,0 +1,49 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
|
||||
large_client_header_buffers 4 32k;
|
||||
client_max_body_size 50M;
|
||||
charset utf-8;
|
||||
|
||||
access_log /var/log/taiga/nginx.access.log;
|
||||
error_log /var/log/taiga/nginx.error.log;
|
||||
|
||||
# Frontend
|
||||
location / {
|
||||
root ${DATA}/taiga-front-dist/dist/;
|
||||
try_files ${ESC}uri ${ESC}uri/ /index.html;
|
||||
}
|
||||
|
||||
# Backend
|
||||
location /api {
|
||||
proxy_set_header Host ${ESC}http_host;
|
||||
proxy_set_header X-Real-IP ${ESC}remote_addr;
|
||||
proxy_set_header X-Scheme ${ESC}scheme;
|
||||
proxy_set_header X-Forwarded-Proto ${ESC}scheme;
|
||||
proxy_set_header X-Forwarded-For ${ESC}proxy_add_x_forwarded_for;
|
||||
proxy_pass http://127.0.0.1:8001/api;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
# Django admin access (/admin/)
|
||||
location /admin {
|
||||
proxy_set_header Host ${ESC}http_host;
|
||||
proxy_set_header X-Real-IP ${ESC}remote_addr;
|
||||
proxy_set_header X-Scheme ${ESC}scheme;
|
||||
proxy_set_header X-Forwarded-Proto ${ESC}scheme;
|
||||
proxy_set_header X-Forwarded-For ${ESC}proxy_add_x_forwarded_for;
|
||||
proxy_pass http://127.0.0.1:8001${ESC}request_uri;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
# Static files
|
||||
location /static {
|
||||
alias ${DATA}/static;
|
||||
}
|
||||
|
||||
# Media files
|
||||
location /media {
|
||||
alias ${DATA}/media;
|
||||
}
|
||||
}
|
5
taiga-db.env
Normal file
5
taiga-db.env
Normal file
@ -0,0 +1,5 @@
|
||||
TAIGA_DB_USER=taiga
|
||||
TAIGA_DB_NAME=taiga
|
||||
TAIGA_DB_PASSWORD=secretpassword
|
||||
TAIGA_DB_HOST=postgres
|
||||
TAIGA_DB_PORT=5432
|
Loading…
Reference in New Issue
Block a user