Browse Source

Add documentation and refactoring for file permissions

devel
Dmitry Novikov 7 years ago
parent
commit
2a6822ae0b
  1. 1
      .gitignore
  2. 2
      README.md
  3. 0
      agent/downloader.py
  4. 0
      agent/monitoring_agent.py
  5. 0
      agent/netflow/netflow_handler.py
  6. 0
      agent/netflow/start_netflow.sh
  7. 0
      devapp/expect_scripts/dlink_DGS1100_reboot.exp
  8. 0
      devapp/expect_scripts/f601.py
  9. 0
      dhcp_lever.py
  10. 210
      dialing.py
  11. 31
      djing/local_settings.py.example
  12. 0
      docs/ats.md
  13. 310
      docs/install_debian.md
  14. 74
      docs/install_fedora.md
  15. 13
      install/djing.ini
  16. 37
      install/install_debian.sh
  17. 42
      install/nginx_server.conf
  18. 4
      install/robots.txt
  19. 0
      manage.py
  20. 0
      periodic.py
  21. 6
      requirements.txt

1
.gitignore

@ -1,6 +1,5 @@
*.pyc *.pyc
*.db *.db
*.txt
media/* media/*
media/min/* media/min/*
~*/migrations/00*.py ~*/migrations/00*.py

2
README.md

@ -6,7 +6,7 @@
Использовано python 3, django 2, bootstrap 3, и другое в файле requirements.txt Использовано python 3, django 2, bootstrap 3, и другое в файле requirements.txt
## Содержание ## Содержание
* [Установка](./docs/install.md)
* [Установка](./docs/install_debian.md)
* [Сервисы и API](./docs/services.md) * [Сервисы и API](./docs/services.md)
* [Менеджеры устройств](./docs/dev.md) * [Менеджеры устройств](./docs/dev.md)
* [Сбор информации трафика по netflow](./docs/netflow.md) * [Сбор информации трафика по netflow](./docs/netflow.md)

0
agent/downloader.py

0
agent/monitoring_agent.py

0
agent/netflow/netflow_handler.py

0
agent/netflow/start_netflow.sh

0
devapp/expect_scripts/dlink_DGS1100_reboot.exp

0
devapp/expect_scripts/f601.py

0
dhcp_lever.py

210
dialing.py

@ -1,210 +0,0 @@
#!/usr/bin/env python3
from typing import Dict, Optional, AnyStr
import re
import signal
from time import sleep
from urllib.parse import urlencode
from urllib.request import urlopen
from urllib.error import HTTPError
from hashlib import sha256
from pid.decorator import pidfile
from djing.lib.messaging.sms import SmsSubmit, SmsDeliver
from asterisk import manager as ast_mngr
ASTERISK_MANAGER_AUTH = {
'username': 'admin',
'password': 'password',
'host': '127.0.0.1'
}
API_AUTH_SECRET = 'your api secret'
SERVER_DOMAIN = 'http://localhost:8000'
outbox_messages = False
def calc_hash(data):
if type(data) is str:
result_data = data.encode('utf-8')
else:
result_data = bytes(data)
return sha256(result_data).hexdigest()
def secure_request(data: Dict) -> Optional[AnyStr]:
vars_to_hash = [str(v) for v in data.values()]
vars_to_hash.sort()
vars_to_hash.append(API_AUTH_SECRET)
sign = calc_hash('_'.join(vars_to_hash))
data.update({'sign': sign})
try:
with urlopen("%s/dialing/api/sms/?%s" % (SERVER_DOMAIN, urlencode(data))) as r:
return r.read()
except ConnectionRefusedError:
print('ERROR: connection refused')
except HTTPError as e:
print('ERROR:', e)
class SMS(object):
def __init__(self, text, who, dev):
self.text = text
self.who = who
self.dev = dev
def __add__(self, other):
if not isinstance(other, SMS):
raise TypeError
if self.who == other.who and self.dev == other.dev:
self.text += other.text
return self
def __str__(self):
return "%s: %s" % (self.who, self.text)
class ChunkedMsg(object):
def __init__(self, sms_count, ref, sms):
self.sms_count = sms_count
self.ref = ref
self.sms = sms
class MyAstManager(ast_mngr.Manager):
sms_chunks = list()
def new_chunked_sms(self, count, ref, sms):
msg = ChunkedMsg(count, ref, sms)
self.sms_chunks.append(msg)
@staticmethod
def save_sms(sms):
print('Inbox %s:' % sms.who, sms.text)
if not isinstance(sms, SMS):
raise TypeError
response = secure_request({
'who': sms.who,
'dev': sms.dev,
'text': sms.text,
'cmd': 'save_sms'
})
if response is not None:
print(response)
def send_sms(self, dev, recipient, utext):
if not validate_tel(recipient):
print("Tel %s is not valid" % recipient)
return
sms = SmsSubmit(recipient, utext)
for pdu in sms.to_pdu():
response = self.command('dongle pdu %s %s' % (dev, pdu.pdu))
print(response.data)
def push_text(self, sms, ref, cnt):
if not isinstance(sms, SMS):
raise TypeError
chunk = [c for c in self.sms_chunks if c.ref == ref]
chunk_len = len(chunk)
if chunk_len == 1:
chunk = chunk[0]
chunk.sms += sms
if chunk.sms_count == cnt:
self.save_sms(chunk.sms)
self.sms_chunks.remove(chunk)
elif chunk_len == 0:
self.new_chunked_sms(cnt, ref, sms)
def send_from_outbox(self):
messages = secure_request({'cmd': 'get_new'})
for msg in messages:
if self.send_sms(dev='sim_8318999', recipient=msg.dst, utext=msg.text):
msg_status = 'st'
else:
msg_status = 'fd'
result = secure_request({
'cmd': 'update_status',
'mid': msg.pk,
'status': msg_status
})
if result is not None:
print(result)
manager = MyAstManager()
def validate_tel(tel, reg=re.compile(r'^\+7978\d{7}$')):
return bool(re.match(reg, tel))
def handle_shutdown(event, mngr):
print("Received shutdown event")
mngr.close()
# we could analyze the event and reconnect here
def signal_handler(signum, frame):
if signum != 10:
return
global outbox_messages
outbox_messages = True
def handle_inbox_long_sms_message(event, mngr):
if event.has_header('Message'):
pdu = event.get_header('Message')
pdu = re.sub(r'^\+CMGR:\s\d,,\d{1,3}\\r\\n', '', pdu)
sd = SmsDeliver(pdu)
data = sd.data
chunks_count = data.get('cnt')
sms = SMS(
text=data.get('text'),
who=data.get('number'),
dev=event.get_header('Device')
)
if chunks_count is not None:
# more than 1 message
mngr.push_text(sms=sms, ref=data.get('ref'), cnt=chunks_count)
else:
# one message
mngr.save_sms(sms)
@pidfile(pidname='dialing.py.pid', piddir='/run')
def main():
global outbox_messages
try:
manager.connect(ASTERISK_MANAGER_AUTH['host'])
manager.login(ASTERISK_MANAGER_AUTH['username'], ASTERISK_MANAGER_AUTH['password'])
# register some callbacks
manager.register_event('Shutdown', handle_shutdown)
manager.register_event('DongleNewCMGR', handle_inbox_long_sms_message) # PDU Here
# get a status report
response = manager.status()
print(response)
signal.signal(signal.SIGUSR1, handler=signal_handler)
while True:
if outbox_messages:
outbox_messages = False
manager.send_from_outbox()
sleep(5)
except ast_mngr.ManagerSocketException as e:
print("Error connecting to the manager: ", e)
except ast_mngr.ManagerAuthException as e:
print("Error logging in to the manager: ", e)
except ast_mngr.ManagerException as e:
print("Error: ", e)
finally:
manager.logoff()
if __name__ == '__main__':
main()

31
djing/local_settings.py.example

@ -1,6 +1,7 @@
""" """
Custom settings for each system Custom settings for each system
""" """
import os
DEBUG = True DEBUG = True
@ -13,23 +14,23 @@ PAGINATION_ITEMS_PER_PAGE = 20
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '!!!!!!!!!!!!!!!!!!!!!!!!YOUR SECRET KEY!!!!!!!!!!!!!!!!!!!!!!!!' SECRET_KEY = '!!!!!!!!!!!!!!!!!!!!!!!!YOUR SECRET KEY!!!!!!!!!!!!!!!!!!!!!!!!'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATABASES = { DATABASES = {
'default': { 'default': {
#'OPTIONS': {
# 'init_command': "SET sql_mode='STRICT_TRANS_TABLES', default_storage_engine=INNODB",
# 'isolation_level': 'read uncommitted'
#},
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#'ENGINE': 'django.db.backends.mysql',
#'NAME': 'djing_db',
#'USER': 'DJING_MYSQL_USERNAME', # You can change the user name
#'PASSWORD': 'DJING_MYSQL_PASSWORD', # You can change the password
#'HOST': 'localhost',
#'TEST': {
# 'CHARSET': 'utf8',
# 'COLLATION': 'utf8_general_ci'
#}
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES', default_storage_engine=INNODB",
'isolation_level': 'read uncommitted'
},
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djing_db',
'USER': 'djinguser', # You can change the user name
'PASSWORD': 'password', # You can change the password
'HOST': 'localhost',
'TEST': {
'CHARSET': 'utf8',
'COLLATION': 'utf8_general_ci'
}
} }
} }

0
docs/ats.md

310
docs/install_debian.md

@ -0,0 +1,310 @@
## Установка:
Работа предполагается на python3.
Я предпочитаю запускать wsgi сервер на связке uWSGI + Nginx, так что ставить будем соответствующие пакеты.
##### Подготовка системы
Установка происходит в debian версии 9.5.
Для начала подготовим систему, очистим и обновим пакеты. Процесс обновления долгий, так что можно пойти заварить себе чай :)
```
# dnf clean all
# dnf -y update
```
Затем установим зависимости, в Fedora 25 пакеты называются так:
```
# dnf -y install python3 python3-devel python3-pip python3-pillow mariadb mariadb-devel uwsgi nginx uwsgi-plugin-python3 net-snmp net-snmp-libs net-snmp-utils net-snmp-devel net-snmp-python git redhat-rpm-config curl-devel expect
```
Для Debian 9 это выглядит так:
```
# apt install mariadb-server libmariadb-dev mariadb-client python3-dev python3-pip python3-pil uwsgi nginx uwsgi-plugin-python3 libsnmp-dev git gettext libcurl4-openssl-dev libssl-dev expect
```
Условимся что путь к папке с проектом находится по адресу: */var/www/djing*.
Дальше создадим каталок для web, затем создаём virtualenv, обновляем pip и ставим проект через pip:
```bash
# mkdir /var/www
# cd /var/www
# git clone --depth=1 https://github.com/nerosketch/djing.git
# python3 -m venv venv
# cd djing
# source ./venv/bin/activate
# pip3 install --upgrade pip
# export PYCURL_SSL_LIBRARY=openssl
# pip3 install -r djing/requirements.txt
# chown -R www-data:www-data /var/www/djing
# deactivate
```
Или, вместо этих комманд выполните инстальник из *install/install_debian.sh* если у вас *debian*,
или по аналогии для других дистрибутивов.
Теперь давайте перейдём в баш от имени пользователя www-data, так у нас будет хватать прав на все
директории и файлы
```bash
sudo -u www-data -g www-data bash && cd /
```
Скопируем конфиг из примера в реальный:
```bash
$ cd /var/www/djing
$ cp djing/local_settings.py.example djing/settings.py
```
Затем отредактируйте конфиг для своих нужд.
В Debian использую пользователя www-data, остаётся только назначить владельца на папки:
```bash
# chown -R www-data:www-data /var/www/djing
```
### Настройка WEB Сервера
Конфиг Nginx в папке *sites-available* на моём рабочем сервере выглядит примерно так как указано
ниже, не забудьте указать в нужных местах ваш домен.
```nginx
upstream djing{
server unix:///run/uwsgi/app/djing/socket;
}
# Для обращений в web серверу на localhost из скриптов
server {
listen 80;
server_name localhost 127.0.0.1;
location / {
uwsgi_pass djing;
include uwsgi_params;
}
access_log /dev/null;
error_log /dev/null;
}
# Это редирект с http на https, если у вас есть ssl сертификат
server{
listen 80;
server_name your-domain.com;
return 301 https://your-domain.com$request_uri;
}
# обработка http запросов.
server {
listen 80 default_server;
server_name <ваш домен>;
root /var/www/djing/;
charset utf-8;
location = /favicon.ico { alias /var/www/djing/static/img/favicon_m.ico; }
location = /robots.txt { alias /var/www/djing/robots.txt; }
location /media {
alias /var/www/djing/media;
expires 7d;
}
location /static {
alias /var/www/djing/static;
expires 1d;
}
location / {
uwsgi_pass djing;
include uwsgi_params;
}
}
# Обработка https запросов
server {
listen 443 ssl;
ssl on;
server_name <ваш домен> www.<ваш домен>;
ssl_certificate "/путь/к/вашему/сертификату.crt";
ssl_certificate_key "/путь/к/вашему/сертификату.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location = /favicon.ico { alias /var/www/djing/static/img/favicon_m.ico; }
location = /robots.txt { alias /var/www/djing/robots.txt; }
location /media {
alias /var/www/djing/media;
expires 7d;
}
location /static {
alias /var/www/djing/static;
expires 1d;
}
location / {
uwsgi_pass djing;
include uwsgi_params;
}
}
```
Это минимальный конфиг Nginx для работы. Проверте файл /run/uwsgi/djing.sock на доступность пользователю www-data для чтения.
Далее настраиваем uWSGI. Мой конфиг для uWSGI в debian:
> /etc/uwsgi/apps-available/djing.ini
```ini
[uwsgi]
chdir=/var/www/djing
module=djing.wsgi
master=True
processes=8
socket=/run/uwsgi/app/djing/socket
;http-socket=:8000
chmod-socket=644
;pidfile=/run/uwsgi/django-master.pid
vacuum=True
plugin=python3
;disable-logging=True
venv=/var/www/djing/venv
```
А теперь попробуем запустить биллинг в полной связке Python - Uwsgi - Nginx.
Перейдём в папку биллинга, если вы вышли куда-то ещё, зайдём в баш из под пользователя www-data.
```bash
sudo -u www-data -g www-data bash
cd /var/www/djing
source ./venv/bin/activate
```
И скомпилируем переводы:
> \$ ./manage.py compilemessages -l ru
Попробуем запустить *uwsgi* и *djing* без *Nginx*, на порт 8000:
Раскомментируйте строку *http-socket=:8000* в файле *djing.ini*, и закомментируйте
*socket=/run/uwsgi/app/djing/socket* и *chmod-socket=644*, теперь можно попробовать запустить
> \# uwsgi --gid www-data --uid www-data /etc/uwsgi/apps-available/djing.ini
пробуем зайти в биллинг с браузера на <адрес сервера>:8000. Вам должен показаться диалог входа в систему:
![Login screenshot](./img/login.png)
Теперь, если всё прошло успешно, поменяйте в конфиге */etc/uwsgi.d/djing.ini* сокет с http-socket на unix socket:
Раскомментируйте это:
> socket=/run/uwsgi/app/djing/socket
И закомментируйте эту строку:
> http-socket=:8000
Строка *http-socket=:8000* была для теста, чтоб посмотреть работает-ли uwsgi сам по себе.
Теперь можно попробовать запустить *nginx* и *uwsgi*. Ставим в **djing/settings.py** опцию **DEBUG = False**,
и пробуем запустить нужные юниты:
> \# systemctl start uwsgi\
> \# systemctl start nginx
### Настраиваем биллинг
Все настройки биллинга находятся в файле *djing/settings.py*. Большинство опций вы можете найти в документации
[Django settings](https://docs.djangoproject.com/en/2.1/ref/settings).
Те опции, которые были добавлены мной в рамках проекта *djing*, описаны ниже в этом разделе документации по установке.
#### djing/settings.py
**USE_TZ** &mdash; Это опция *Django*, но если вы не работаете в разных часовых диапазонах то я не рекомендую включать
эту опцию чтоб небыло путаницы со временем. Это связано с тем что я ещё не тестировал поведение работы со временем при
включённой опции *USE_TZ*.
**ALLOWED_HOSTS** &mdash; Тоже опция *Django*, но важная для безопасности, укажите в списке возможные имена вашего сервера.
Подробнее в документации [Django settings](https://docs.djangoproject.com/en/2.1/ref/settings/#allowed-hosts).
**DEFAULT_PICTURE** &mdash; Это путь к изображению по умолчанию, оно используется когда нужное изображение не найдено.
**PAGINATION_ITEMS_PER_PAGE** &mdash; Количество выводимых элементов списка на странце с таблицей. Например, если поставить 30,
то на странице абонентов на одной странице будет выведено 30 строк абонентов.
**DEFAULT_SNMP_PASSWORD** &mdash; Пароль snmp по умолчанию для устройств, чтоб при создании устройства он был заполнен в нужном поле.
Если нет такого пароля то оставьте пустым или None.
**TELEPHONE_REGEXP** &mdash; Регулярное выражение для валидации номера телефона.
**API_AUTH_SECRET** &mdash; Секретное слово для безопасной передачи комманд от скриптов.
Содержимое данных можно увидеть, но нельзя изменить. Это нельзя применять для передачи паролей,
секретных номеров, но вполне подходит для защищённого управления. Безопасность гарантируется хеш суммой
__sha256__. Секретное слово должен знать биллинг в конфиге, и доверенный скрипт на примере *agent/monitoring_agent.py*
Позаботьтесь о том чтоб скрипт нельзя было просто так прочитать, или вынесите секретное слово куда-то. Если кто-то лишний узнает
его то ваша система будет под угрозой.
**API_AUTH_SUBNET** &mdash; Так же применяется для авторизации скриптов, но проверяет подсеть с которой была отправлена
комманда. Даже если скрипт будет знать секретное слово, но не будет находится в одной из доверенных
подсетей то в доступе будет отказано. Может быть строковым представлением подсети, например '127.0.0.1/8', или списком
подсетей в строковом представлении. Можно даже передать объект который на выходе при преобразовании в строку
даст подсеть.
**COMPANY_NAME** &mdash; Название вашей компании, будет отображаться в шапке сайта в административной части
и в личном кабинете абонента.
**TELEGRAM_BOT_TOKEN** &mdash; Когда вы включите оповещение через телеграм то вам сюда.
#### Создание БД
Подразумевается что сервер баз данных у вас уже есть, или вы его можете установить сами.
В конфиге настроить БД можно по инструкции [Django databases](https://docs.djangoproject.com/en/2.1/ref/settings/#databases).
Убедитесть что вы в папке с проектом, комманда **pwd** должна выдать */var/www/djing*.
Чтоб создать бд, как описано в документации [Django admin \& migrate](https://docs.djangoproject.com/en/2.1/ref/django-admin/#migrate),
нужно запустить **./manage.py migrate** чтоб создать структуру БД. Вывод будет примерно таким:
```
$ ./manage.py migrate
Operations to perform:
Apply all migrations: mapapp, contenttypes, msg_app, taskapp, accounts_app, devapp, statistics, tariff_app, admin, sessions, chatbot, auth, abonapp
Running migrations:
Rendering model states... DONE
Applying mapapp.0001_initial... OK
Applying devapp.0001_initial... OK
Applying devapp.0002_auto_20160909_1018... OK
Applying devapp.0003_device_map_dot... OK
Applying contenttypes.0001_initial... OK
...
Applying taskapp.0012_auto_20170407_0124... OK
Applying taskapp.0013_auto_20170413_1944... OK
Applying taskapp.0014_auto_20170416_1029... OK
Applying taskapp.0015_auto_20170816_1109... OK
```
После этого вам стоит создать супер пользователя чтоб зайти в систему.
```
$ ./manage.py createsuperuser
```
В интерактивном режиме ответьте на вопросы.
```
$ ./manage.py createsuperuser
Username: username
Telephone: +12223334455
Password:
Password (again):
Superuser created successfully.
```
Обратите внимание на то что номер телефона это обязательное поле для заполнения.
Если у вас не выходит указать номер телефона, то проверте чтоб ваш телефон соответствовал регулярному выражению **^(\+[7,8,9,3]\d{10,11})?$**.
Если регулярное выражение вам не подхожит, то вы можете изенить его в настройках, см. опции в настройках выше.
После изменения настроек они не сразу вступят в силу, нужно перезагрузить код django, для этого перезапустите **uwsgi**:
> \# systemctl restart uwsgi
Теперь произведите тестовый запуск:
> \$ ./manage.py runserver 192.168.0.100:8000
Если не подтягивается статика то проверте чтоб опция **DEBUG** в настройках была **True**.
При условии что адрес вашего сервера *192.168.0.100*, вы сможете открыть биллинг по адресу **http://192.168.0.100:8000/**.
Введите логин и пароль супер пользователя которого вы создали по инструкции выше.
Если вы успешно зашли то можно пробовать запускать биллинг в рабочую обстановку.
В настройках смените переменную **DEBUG** на **False** и перезапустите *uwsgi*.
### Настраиваем демоны
Если ваша система работает с поддержкой [**systemd**](https://www.freedesktop.org/wiki/Software/systemd/) то в каталоге *systemd_units* проекта вы найдёте юниты для systemd.
Скопируйте их в каталог юнитов systemd, у меня это путь */etc/systemd/system*.
__Настоятельно рекомендую заглянуть внутрь этих юнитов__. Проверте пути исполняемых файлов, права и прочее.
Для запуска сервиса **djing_rotate.service** вам нужно сначала настроить сбор статистики по [netflow](./netflow.md).
Перед включением юнита *djing_telebot.service* создайте Telegram бота и впишите в файл *djing/settings.py* в переменную *TELEGRAM_BOT_TOKEN* токен вашего бота.
С помощью этого бота вы будете получать различные сообщения из биллинга. Подробнее в инструкции к [модулю оповещений](./bot.md).

74
docs/install.md → docs/install_fedora.md

@ -2,7 +2,7 @@
Работа предполагается на python3. Работа предполагается на python3.
Я предпочитаю запускать wsgi сервер на связке uWSGI + Nginx, так что ставить будем соответствующие пакеты. Я предпочитаю запускать wsgi сервер на связке uWSGI + Nginx, так что ставить будем соответствующие пакеты.
##### Подготовка системы
##### На Fedora25 нужные пакеты можно установить так:
Для начала подготовим систему, очистим и обновим пакеты. Процесс обновления долгий, так что можно пойти заварить себе чай :) Для начала подготовим систему, очистим и обновим пакеты. Процесс обновления долгий, так что можно пойти заварить себе чай :)
``` ```
@ -10,41 +10,38 @@
# dnf -y update # dnf -y update
``` ```
Затем установим зависимости, в Fedora 25 пакеты называются так:
Затем установим зависимости
``` ```
# dnf -y install python3 python3-devel python3-pip python3-pillow mariadb mariadb-devel uwsgi nginx uwsgi-plugin-python3 net-snmp net-snmp-libs net-snmp-utils net-snmp-devel net-snmp-python git redhat-rpm-config curl-devel expect
# dnf -y install python3 python3-devel python3-pip python3-pillow \
mariadb mariadb-devel uwsgi nginx uwsgi-plugin-python3 net-snmp \
net-snmp-libs net-snmp-utils net-snmp-devel net-snmp-python \
git redhat-rpm-config
``` ```
Для Debian 9 это выглядит так:
Лучше чтоб версия python по умолчанию была третья:
``` ```
# apt install mariadb-server libmariadb-dev mariadb-client python3-dev python3-pip python3-pil uwsgi nginx uwsgi-plugin-python3 libsnmp-dev git gettext libcurl4-openssl-dev libssl-dev expect
# ln -sf python3 /usr/bin/python
``` ```
Условимся что путь к папке с проектом находится по адресу: */var/www/djing*. Условимся что путь к папке с проектом находится по адресу: */var/www/djing*.
Дальше создадим каталок для web, затем создаём virtualenv, обновляем pip и ставим проект через pip:
Дальше создадим каталок для web, затем обновляем pip и ставим проект через pip:
``` ```
# mkdir /var/www # mkdir /var/www
# cd /var/www # cd /var/www
# git clone --depth=1 https://github.com/nerosketch/djing.git
# chown -R http:http djing
# python3 -m venv venv
# sudo -u http -g http bash
$ cd djing
$ source ./venv/bin/activate
$ pip3 install --upgrade pip
$ export PYCURL_SSL_LIBRARY=openssl
$ pip3 install -r djing/requirements.txt
# pip3 install --upgrade pip
# git clone https://github.com/nerosketch/djing.git
# pip3 install -r djing/requirements.txt
``` ```
Скопируем конфиг из примера в реальные:
Скопируем конфиги из примеров в реальные:
``` ```
$ cd /var/www/djing $ cd /var/www/djing
$ cp djing/local_settings.py.example djing/settings.py
# cp djing/settings_example.py djing/settings.py
``` ```
Затем отредактируйте конфиг для своих нужд.
Затем отредактируйте конфиги для своих нужд.
Для удобства в Fedora я создаю пользователя и группу http:http, и всё что связано с web-сервером запускаю от имени http.
Для удобства я создаю пользователя и группу http:http, и всё что связано с web-сервером запускаю от имени http.
``` ```
# groupadd -r http # groupadd -r http
# useradd -l -M -r -d /dev/null -g http -s /sbin/nologin http # useradd -l -M -r -d /dev/null -g http -s /sbin/nologin http
@ -54,15 +51,6 @@ $ cp djing/local_settings.py.example djing/settings.py
# chown -R http:http /run/uwsgi/ # chown -R http:http /run/uwsgi/
``` ```
В Debian использую пользователя www-data, остаётся только назначить владельца на папки:
```
# chown -R http:http /var/www
# chown -R http:http /etc/nginx
# chown -R http:http /etc/uwsgi.*
# chown -R http:http /run/uwsgi/
```
### Настройка WEB Сервера ### Настройка WEB Сервера
Конфиг Nginx на моём рабочем сервере выглядит так: Конфиг Nginx на моём рабочем сервере выглядит так:
```nginx ```nginx
@ -212,21 +200,13 @@ plugin=python3
**PAGINATION_ITEMS_PER_PAGE** &mdash; Количество выводимых элементов списка на странце с таблицей. Например, если поставить 30, **PAGINATION_ITEMS_PER_PAGE** &mdash; Количество выводимых элементов списка на странце с таблицей. Например, если поставить 30,
то на странице абонентов на одной странице будет выведено 30 строк абонентов. то на странице абонентов на одной странице будет выведено 30 строк абонентов.
**PAY_SERV_ID** &mdash; Эта опция, так же как и **PAY_SECRET** опции для платёжной системы *AllTime24*, если вы используете любую
другую платёжную систему то можете удалить эти опции.
**DIALING_MEDIA** &mdash; Путь, где биллинг сможет найти файлы записей asterisk чтоб вывести статистику звонков.
Подробнее читайте в описании работы с [АТС](./ats.ms).
**DEFAULT_SNMP_PASSWORD** &mdash; Пароль snmp по умолчанию для устройств, чтоб при создании устройства он был заполнен в нужном поле. **DEFAULT_SNMP_PASSWORD** &mdash; Пароль snmp по умолчанию для устройств, чтоб при создании устройства он был заполнен в нужном поле.
Если нет такого пароля то оставьте пустым или None. Если нет такого пароля то оставьте пустым или None.
**TELEPHONE_REGEXP** &mdash; Регулярное выражение для валидации номера телефона. **TELEPHONE_REGEXP** &mdash; Регулярное выражение для валидации номера телефона.
**ASTERISK_MANAGER_AUTH** &mdash; Данные для управления АТС [Asterisk](https://www.asterisk.org/), пример заполнения есть в *djing/settings_example.py*.
**API_AUTH_SECRET** &mdash; Секретное слово для безопасной передачи комманд от скриптов. **API_AUTH_SECRET** &mdash; Секретное слово для безопасной передачи комманд от скриптов.
Содержимое данных можно увидеть, но нельзя изменить. Это нельзя применять лоя передачи паролей,
Содержимое данных можно увидеть, но нельзя изменить. Это нельзя применять для передачи паролей,
секретных номеров, но вполне подходит для защищённого управления. Безопасность гарантируется хеш суммой секретных номеров, но вполне подходит для защищённого управления. Безопасность гарантируется хеш суммой
__sha256__. то секретное слово должен знать биллинг в конфиге, и доверенный скрипт на примере *agent/monitoring_agent.py.py* __sha256__. то секретное слово должен знать биллинг в конфиге, и доверенный скрипт на примере *agent/monitoring_agent.py.py*
Позаботьтесь о том чтоб скрипт нельзя было просто так прочитать, или вынесите секретное слово куда-то. Если кто-то лишний узнает Позаботьтесь о том чтоб скрипт нельзя было просто так прочитать, или вынесите секретное слово куда-то. Если кто-то лишний узнает
@ -288,10 +268,12 @@ Superuser created successfully.
После изменения настроек они не сразу вступят в силу, нужно перезагрузить код django, для этого перезапустите **uwsgi**: После изменения настроек они не сразу вступят в силу, нужно перезагрузить код django, для этого перезапустите **uwsgi**:
> \# systemctl restart uwsgi > \# systemctl restart uwsgi
Теперь произведите тестовый запуск:
Теперь произведите тестовый запуск, например:
> \# ./manage.py runserver 192.168.0.100:8000 > \# ./manage.py runserver 192.168.0.100:8000
Если не подтягивается статика то проверте чтоб опция **DEBUG** в настройках была **True**.
Если не подтягивается статика то проверте чтоб опция **DEBUG** в настройках была **True**,
но в реальном окружении лучше Debug отключить, подробнее об этом тут:
[docs.djangoproject.com/en/2.1/ref/settings](https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-DEBUG)
При условии что адрес вашего сервера *192.168.0.100*, вы сможете открыть биллинг по адресу **http://192.168.0.100:8000/**. При условии что адрес вашего сервера *192.168.0.100*, вы сможете открыть биллинг по адресу **http://192.168.0.100:8000/**.
Введите логин и пароль супер пользователя которого вы создали по инструкции выше. Введите логин и пароль супер пользователя которого вы создали по инструкции выше.
@ -300,7 +282,8 @@ Superuser created successfully.
В настройках смените переменную **DEBUG** на **False** и перезапустите *uwsgi*. В настройках смените переменную **DEBUG** на **False** и перезапустите *uwsgi*.
### Настраиваем демоны ### Настраиваем демоны
Если ваша система работает с поддержкой [**systemd**](https://www.freedesktop.org/wiki/Software/systemd/) то в каталоге *systemd_units* проекта вы найдёте юниты для systemd.
Если ваша система работает с поддержкой [**systemd**](https://www.freedesktop.org/wiki/Software/systemd/)
то в каталоге *systemd_units* проекта вы найдёте юниты для systemd.
Скопируйте их в каталог юнитов systemd, у меня это путь */etc/systemd/system*. Скопируйте их в каталог юнитов systemd, у меня это путь */etc/systemd/system*.
__Настоятельно рекомендую заглянуть внутрь этих юнитов__. Проверте пути исполняемых файлов, права и прочее. __Настоятельно рекомендую заглянуть внутрь этих юнитов__. Проверте пути исполняемых файлов, права и прочее.
@ -308,14 +291,3 @@ __Настоятельно рекомендую заглянуть внутрь
Перед включением юнита *djing_telebot.service* создайте Telegram бота и впишите в файл *djing/settings.py* в переменную *TELEGRAM_BOT_TOKEN* токен вашего бота. Перед включением юнита *djing_telebot.service* создайте Telegram бота и впишите в файл *djing/settings.py* в переменную *TELEGRAM_BOT_TOKEN* токен вашего бота.
С помощью этого бота вы будете получать различные сообщения из биллинга. Подробнее в инструкции к [модулю оповещений](./bot.md). С помощью этого бота вы будете получать различные сообщения из биллинга. Подробнее в инструкции к [модулю оповещений](./bot.md).
А теперь включим и запустим нужные демоны
```shell
# systemctl daemon-reload
# systemctl enable djing_queue.service
# systemctl start djing_queue.service
# systemctl enable djing_rotate.timer
# systemctl start djing_rotate.timer
# systemctl enable djing_telebot.service
# systemctl start djing_telebot.service
```

13
install/djing.ini

@ -0,0 +1,13 @@
[uwsgi]
chdir=/var/www/djing
module=djing.wsgi
master=True
processes=8
socket=/run/uwsgi/app/djing/socket
;http-socket=:8000
chmod-socket=644
;pidfile=/run/uwsgi/django-master.pid
vacuum=True
plugin=python3
;disable-logging=True
venv=/var/www/djing/venv

37
install/install_debian.sh

@ -2,19 +2,25 @@
PATH=/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin PATH=/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
apt-get -y update
apt -y update
apt -y upgrade
sleep 1 sleep 1
apt-get -y upgrade
sleep 1
apt-get -y install mariadb-server libmariadb-dev mariadb-client python3-dev python3-pip python3-pil python3-venv uwsgi nginx uwsgi-plugin-python3 libsnmp-dev git gettext libcurl4-openssl-dev libssl-dev expect
apt -y install mariadb-server libmariadb-dev libmariadbclient-dev \
mariadb-client python3-dev python3-pip python3-pil python3-venv uwsgi \
nginx uwsgi-plugin-python3 libsnmp-dev git gettext libcurl4-openssl-dev \
libssl-dev expect
sleep 3 sleep 3
mkdir -p /var/www mkdir -p /var/www
cd /var/www cd /var/www
mysql -u root -e "create database djing_db charset utf8 collate utf8_general_ci;"
mysql -u root -e "create user 'djinguser'@'localhost' identified by 'password';"
mysql -u root -e "grant all privileges on djing_db.* to 'djinguser'@'localhost';"
mysql -u root -e "flush privileges;"
git clone https://github.com/nerosketch/djing.git -b devel djing git clone https://github.com/nerosketch/djing.git -b devel djing
cd djing cd djing
python3 -m venv venv python3 -m venv venv
@ -22,7 +28,24 @@ source ./venv/bin/activate
pip3 install --upgrade pip pip3 install --upgrade pip
export PYCURL_SSL_LIBRARY=openssl export PYCURL_SSL_LIBRARY=openssl
pip3 install -r requirements.txt pip3 install -r requirements.txt
cp djing/local_settings.py.example djing/settings.py
cp djing/local_settings.py.example djing/local_settings.py
./manage.py migrate
./manage.py compilemessages -l ru
deactivate deactivate
chown -R www-data:www-data /var/www
cp install/robots.txt robots.txt
cp install/djing.ini /etc/uwsgi/apps-available/djing.ini
ln -s /etc/uwsgi/apps-available/djing.ini /etc/uwsgi/apps-enabled/djing.ini
cp install/nginx_server.conf /etc/nginx/sites-available/djing.conf
ln -s /etc/nginx/sites-available/djing.conf /etc/nginx/sites-enabled/djing.conf
chown -R www-data:www-data /var/www/djing
# dirs
find . -type d \( -path ./venv -o -path ./src -o -path ./.git \) -prune -o -type d -exec chmod 750 {} \;
# files
find . -type d \( -path ./venv -o -path ./src -o -path ./.git \) -prune -o -type f -exec chmod 640 {} \;
# exec scripts
chmod 750 dhcp_lever.py manage.py periodic.py devapp/expect_scripts/dlink_DGS1100_reboot.exp
chmod 400 djing/settings.py

42
install/nginx_server.conf

@ -0,0 +1,42 @@
upstream djing{
server unix:///run/uwsgi/app/djing/socket;
}
# Для обращений в web серверу на localhost из скриптов
server {
listen 80;
server_name localhost 127.0.0.1;
location / {
uwsgi_pass djing;
include uwsgi_params;
}
access_log /dev/null;
error_log /dev/null;
}
# обработка http запросов.
server {
listen 80 default_server;
server_name _;
root /var/www/djing/;
charset utf-8;
location = /favicon.ico { alias /var/www/djing/static/img/favicon_m.ico; }
location = /robots.txt { alias /var/www/djing/robots.txt; }
location /media {
alias /var/www/djing/media;
expires 7d;
}
location /static {
alias /var/www/djing/static;
expires 1d;
}
location / {
uwsgi_pass djing;
include uwsgi_params;
}
}

4
install/robots.txt

@ -0,0 +1,4 @@
User-agent: *
Allow: /$
Allow: /accounts/login/
Disallow: /

0
manage.py

0
periodic.py

6
requirements.txt

@ -9,8 +9,8 @@ netaddr
#xmltodict #xmltodict
dicttoxml dicttoxml
# db client for Postgres
psycopg2-binary
# db client for Mariadb
mysqlclient
easysnmp easysnmp
pid pid
@ -23,9 +23,7 @@ django-bootstrap3
requests requests
webdavclient webdavclient
pyst2
transliterate transliterate
asterisk
django-encrypted-model-fields django-encrypted-model-fields
# django-xmlview for pay system allpay # django-xmlview for pay system allpay

Loading…
Cancel
Save