Настройка Exim4 / Dovecot в Astra Linux SE 1.5
Настройка почты в Astra Linux 1.5 ALD
Исходные данные и задачи
Необходимо настроить сервер электронной почты, работающий в рамках домена Astra Linux 1.5 SE. Исходные данные:
| Параметр | Значение |
|---|---|
| Имя домена | local.net |
| FQDN сервера | server.local.net |
| IP-адрес сервера | 192.168.0.1 |
| Маска сети: | 255.255.255.0 |
Настройка сети
Отключаем графический менеджер управления сетевыми подключениями wicd.
chkconfig wicd off
Прописываем настройки сети в файле /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
allow-hotplug eth0
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.1
network 192.168.0.0
broadcast 192.168.0.255
dns-nameservers 192.168.0.1
dns-search local.lan
После этого нужно выполнить перезапуск демона сети:
service networking stop && service networking start
В документации к демону networking написано, что команда restart является устаревшей и работает не так, как ожидается.
Необходимо в файле /etc/hosts прописать соответствие FQDN сервера и его IP-адреса, а также задать hostname
127.0.0.1 localhost
192.168.0.1 server.local.net server
192.168.0.101 arm01.local.net arm01
192.168.0.102 arm02.local.net arm02
192.168.0.103 arm03.local.net arm03
В файле /etc/hostname меняем краткое имя компьютера server на полное server.local.net, а также изменяем текущее значение системной переменной:
echo server.local.net > /etc/hostname
hostname server.local.net
Инициализация домена
Действуем согласно официальной инструкции от РусБиТех:
ald-init init
Появится уведомление о том, что команда init уничтожит всю базу данных LDAP и Kerberos, будут остановлены и перезапущены службы, и упадет с неба большая звезда, горящая подобно светильнику, и падет на третью часть рек и на источники вод... Отвечаем утвердительно
Попросят ввести пароли для доступа к базе данных Kerberos и пароль администратора Astra Linux Directory. Лучше записать куда-нибудь, потому что понадобится ещё не раз.
Спустя какое-то время на экране появится сообщение:
Astra Linux Directory сконфигурирована.
Сервер ALD активен.
Клиент ALD включен.
Astra Linux Directory сервер успешно инициализирован.
Установка и настройка почтовых сервисов.
Необходимо установить три пакета:
| Пакет | Описание |
|---|---|
| exim4-daemon-heavy | Передает сообщения и умеет работать с мандатными метками. |
| dovecot-imapd | Умеет отдавать почту клиентам. |
| dovecot-gssapi | Умеет принимать авторизацию на сервере через Kerberos (ALD). |
Отдельно отмечу, что сразу же после установки нужно будет запустить конфигурирование exim4.
aptitude install exim4-daemon-heavy dovecot-imapd dovecot-gssapi -y
dpkg-reconfigure exim4-config
Процесс настройки exim4 не очень сложный, но нужно правильно ответить на несколько вопросов.
| Вопрос | Ответ |
|---|---|
| Общий тип почтовой конфигурации | интернет-сайт; приём и отправка почты напрямую, используя SMTP |
| Почтовое имя системы: | local.net |
| IP-адреса, с которых следует ожидать входящие соединения SMTP: | 192.168.0.1 |
| Другие места назначения, для которых должна приниматься почта: | local.net |
| Домены, для которых доступна релейная передача почты: | Оставляем пустым |
| Машины, для которых доступна релейная передача почты: | Оставляем пустым |
| Сокращать количество DNS-запросов до минимума (дозвон по требованию)? | Нет |
| Метод доставки локальной почты: | Maildir формат в домашнем каталоге |
| Разделить конфигурацию на маленькие файлы? | Да |
Теперь нужно удалить из каталога /var/mail файл с именем пользователя, созданного при установке системы (у меня обычно administrator).
rm /var/mail/administrator
Создадим сервисы ALD для работы с почтой:
ald-admin service-add imap/server.local.lan
ald-admin sgroup-svc-add imap/server.local.lan --sgroup=mac
ald-admin sgroup-svc-add imap/server.local.lan --sgroup=mail
ald-admin service-add smtp/server.local.lan
ald-admin sgroup-svc-add smtp/server.local.lan --sgroup=mac
ald-admin sgroup-svc-add smtp/server.local.lan --sgroup=mail
ald-client update-svc-keytab imap/server.local.lan --ktfile="/var/lib/dovecot/dovecot.keytab"
ald-client update-svc-keytab smtp/server.local.lan --ktfile="/var/lib/dovecot/dovecot.keytab"
Указывая имя сервиса, важно помнить, что после слеша указывается то же самое имя сервера, что и в файле /etc/hostname. Если даже в настройках Bind вы потом укажете, что mail.local.net и smtp.local.net являются всего лишь псевдонимами для server.local.net, почта работать не будет, потому что Kerberos очень строго проверяет этот параметр.
После создания файла ключей нужно предоставить доступ к нему для dovecot:
setfacl -m u:dovecot:x /var/lib/dovecot
setfacl -m u:dovecot:r /var/lib/dovecot/dovecot.keytab
Dovecot
Выполняем настройку dovecot. Если убрать все комментарии из файлов, то получится примерно следующее (в тех файлах, где меняли):
!include_try /usr/share/dovecot/protocols.d/*.protocol
protocols = imap
listen = 192.168.0.1
dict {}
!include conf.d/*.conf
!include_try local.confdisable_plaintext_auth = yes
auth_mechanisms = gssapi
auth_gssapi_hostname = server.local.lan
auth_krb5_keytab = /var/lib/dovecot/dovecot.keytab
!include auth-system.conf.extЯ не могу в настройку SSL. Отключаем:
ssl = no
ssl_cert = </etc/dovecot/dovecot.pem
ssl_key = </dovecot/private/dovecot.pemМаленькая настройка для корректной работы с почтой - добавляем в файле /etc/dovecot/conf.d/10-master.conf в секцию service auth:
# ...
service auth {
unix_listener auth-client {
mode = 0600
user = Debian-exim
}
# ...
}Немного упрощаем себе и пользователям жизнь, автоматически создавая на сервере каталоги под входящие, отправленные и удаленные письма при первой авторизации (параметр auto = subscribe).
namespace inbox {
mailbox Drafts {
special_use = \Drafts
auto = subscribe
}
mailbox Junk {
special_use = \Junk
}
mailbox Trash {
special_use = \Trash
auto = subscribe
}
mailbox Sent {
special_use = \Sent
auto = subscribe
}
}Расположение каталогов внутри /var/mail/%username% можно изменить, сделав более удобным, если в /etc/dovecot/conf.d/10-mail.conf немного изменить параметр mail_location:
mail_location = maildir:/var/mail/%u:LAYOUT=fs
Exim4
Теперь нужно сделать пару дополнительных настроек Exim4.
dovecot_gssapi:
driver = dovecot
public_name = GSSAPI
server_socket = /var/run/dovecot/auth-client
server_set_id = $auth1 # В конце цифра один, а не маленькая эльФайл /etc/exim4/conf.d/acl/30_exim4-config_check_rcpt очень большой, поэтому не привожу его полностью. В самом начале нужно добавить в секцию acl_check_rcpt 4 строки, чтобы выглядело примерно так:
acl_check_rcpt:
deny
message = "Auth required"
hosts = *:+relay_from_hosts
!authenticated = *
accept:
hosts = :
control = dkim_disable_verify
# и так далееПроверка работоспособности
Заходим от имени пользователя ALD. Запускаем Thunderbird и создаем новую учетную запись. В параметрах IMAP- и SMTP-серверов пишем одно и то же - server.local.net. При нажатии кнопки "Проверка параметров" параметры авторизации должны измениться на Kerberos/GSSAPI. Сохраняем, перезапускаем почтовый клиент. После второго запуска должно загрузиться дерево папок с сервера. Пишем письмо сами себе, если пришло - все хорошо. Если нет - очень внимательно проверяем содержимое всех конфигурационных файлов. Я сам потерял три дня из-за того, что в одном месте пропустил всего одну строку.
Настройка GRUB2 в Debian
Зачем настраивать GRUB 2
Решил я настроить свой GRUB 2, потому что не все его параметры меня устраивают. Ну, например, уменьшить таймаут, увеличить разрешение, в конце концов, поменять фоновую картинку. К чему в итоге пришёл, написано ниже.
Настройка разрешения
Первое, что нужно сделать - зайти в консоль самого GRUB'а при запуске. Для этого нужно нажать клавишу c, и, если пароль на загрузчик не установлен, сразу же осуществляется переход к командной строке. Тут вводим одну команду из двух (результат на моём Debian 9 одинаковый):
videoinfo
vbeinfo
Обе команды дают один и тот же результат - список доступных GRUB'у режимов видеоадаптера. Однако, всё не так просто. Дело в том, что при запуске загрузчика загружается видеодрайвер, НО ЭТО НЕ ТОТ ВИДЕОДРАЙВЕР, который даёт полный доступ ко всем режимам видеоадаптера. Таким образом, у меня, например, максимально доступное разрешение не соответствует параметрам монитора, т. е. тут не всё так просто.
В общем, параметры монитора я выяснил, теперь надо было подкрутить /etc/default/grub. Настраивать нужно именно этот файл, поскольку при вызове скрипта update-grub настройки будут взяты оттуда. Ниже привожу только те настройки, которые менял.
GRUB_DEFAULT=0
GRUB_TIMEOUT=3
GRUB_GFXMODE=1280x1024x32 # Разрешение загрузочного меню GRUB
GRUB_GFXPAYLOAD_LINUX=1920x1080x32 # Передается в параметрах ядра
GRUB_BACKGROUND=/etc/alternatives/desktop-theme/grub/Hexagons-16x9.png
GRUB_DISABLE_OS_PROBER="true"
Краткое описание параметров:
| GRUB_DEFAULT | Пункт меню по умолчанию |
| GRUB_TIMEOUT | Время в секундах до загрузки пункта по умолчанию |
| GRUB_GFXMODE | Графический режим загрузчика. Можно указать так же значение auto. |
| GRUB_GFXPAYLOAD_LINUX | Разрешение графического режима, которое загрузчик передаст ядру. Если указать правильное значение, можно запускать ОС сразу с нужным разрешением экрана. |
| GRUB_BACKGROUND | Путь к фону загрузчика. Допускается использовать файлы в форматах jpg, png и tga. При необходимости изображение будет отмасштабировано под GRUB_GFXMODE. Если картинки не будет в указанном месте, загрузчик будет запущен в текстовом режиме, без какой-либо графики. |
| GRUB_DISABLE_OS_PROBER | Запретить запуск утилиты osprober, собирающей информацию о других установленных ОС. Поскольку у меня Linux единственная ОС на этом компьютере, могу себе позволить сэкономить немного времени. |
После настройки всех параметров обязательно нужно вызвать команду update-grub. Для тех систем, где используется GRUB2, данная команда является символической ссылкой на update-grub2.
Elpy, python-mode и use-package
Emacs - отличный редактор для тех, кто пишет на Python, и есть куча пакетов для поддержки этого языка. Я уже раньше писал, что теперь храню свою конфигурацию и управляю пакетами с помощью use-package, однако, долго не мог найти способ для красивого скрещивания замечательного пакета elpy cо стандартным python-mode.
Решение оказалось не очень сложным, хотя на его поиск пришлось потратить некоторое время. Ниже выкладываю кусок своего init.el.
(use-package python-mode
:mode ("\\.py\\'" . python-mode)
:init(add-hook 'python-mode-hook #'elpy-enable)
:config
(use-package elpy
:bind
("M-," . elpy-goto-definition)
:init
(elpy-enable)
(defalias 'workon 'pyvenv-workon)
:config
(add-to-list 'company-backends 'elpy-company-backend)
(elpy-enable))
(use-package py-autopep8
:hook
(python-mode . py-autopep8-enable-on-save))
(use-package py-isort
:init
(add-hook 'before-save-hook #'py-isort-before-save)))
Этот код не делает никакой магии. В общем-то, тут вообще нет ничего интересного.
Самому себе оставляю памятку: в настройках settings.el уже включена автоматическая загрузка недостающих пакетов с помощью use-package. Для всех Python'ьих файлов как major-mode указан python-mode. При его инициализации дополнительно подключаются пакеты elpy, py-autopep8 и py-isort, почти все настройки которых уже вынесены сами знаете куда. Кроме того, каждый пакет при загрузке ставит хуки на определенное действие. Например, автоматическое форматирование или упорядочение импортированных модулей.
Не уверен в том, какую строку с elpy-enable можно удалить, чтобы ничего не сломалось. Сегодня выяснять лень, потом разберусь.
Красивый способ хранения настроек Emacs
Интересный подход к хранению конфигурации Emacs
Интересный способ хранения конфигурации подсмотрел у автора use-package. Если вкратце, то все настройки для конкретных пакетов вынесены в файл settings.el, а вот список используемых пакетов и нюансы взаимодействия между ними описаны целиком и полностью в init.el.
Чтобы далеко не ходить, вот пример кода:
;;; init.el --- Summary
;;; Commentary:
;;; Main EMACS settings file, load settings from parts.
;;; Code:
;; Added by Package.el. This must come before configurations of
;; installed packages. Don't delete this line. If you don't want it,
;; just comment it out by adding a semicolon to the start of the line.
;; You may delete these explanatory comments.
(package-initialize)
(eval-when-compile(require 'cl))
(require 'package)
(setq package-archives nil)
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/") t)
(add-to-list 'package-archives '("elpy" . "https://jorgenschaefer.github.io/packages/") t)
(setq package-enable-at-startup nil)
(package-initialize nil)
;;; Загрузка и установка пакета use-package, если его нет в системе
(unless(package-installed-p 'use-package)
(message "EMACS install use-package.el")
(package-refresh-contents)
(package-install 'use-package))
(require 'use-package)
;;; Шрифты
(set-face-attribute 'default nil :height 110)
(when (member "DejaVu Sans Mono" (font-family-list))
(set-face-attribute 'default nil :font "DejaVu Sans Mono"))
;;; Заставляю хоткеи работать и в русской раскладке
(defun cfg:reverse-input-method (input-method)
"Build the reverse mapping of single letters from INPUT-METHOD."
(interactive
(list (read-input-method-name "Use input method (default current): ")))
(if (and input-method (symbolp input-method))
(setq input-method (symbol-name input-method)))
(let ((current current-input-method)
(modifiers '(nil (control) (meta) (control meta))))
(when input-method
(activate-input-method input-method))
(when (and current-input-method quail-keyboard-layout)
(dolist (map (cdr (quail-map)))
(let* ((to (car map))
(from (quail-get-translation
(cadr map) (char-to-string to) 1)))
(when (and (characterp from) (characterp to))
(dolist (mod modifiers)
(define-key local-function-key-map
(vector (append mod (list from)))
(vector (append mod (list to)))))))))
(when input-method
(activate-input-method current))))
(cfg:reverse-input-method 'russian-computer)
;; Resize windows
(global-set-key(kbd "S-C-") 'shrink-window-horizontally)
(global-set-key(kbd "S-C-") 'enlarge-window-horizontally)
(global-set-key(kbd "S-C-") 'shrink-window)
(global-set-key(kbd "S-C-") 'enlarge-window)
;; Isearch
(global-set-key (kbd "C-M-r") 'isearch-backward-other-window)
(global-set-key (kbd "C-M-s") 'isearch-forward-other-window)
(defun xah-new-empty-buffer()
"Open a new empty buffer.
URL `http: // ergoemacs.org / emacs / emacs_new_empty_buffer.html'
Version 2015 - 06 - 12"
(interactive)
(let((ξbuf(generate-new-buffer "untitled")))
(switch-to-buffer ξbuf)
(funcall(and initial-major-mode))
(setq buffer-offer-save t)))
;; Save/close/open
(global-set-key(kbd "C-w") 'kill-this-buffer)
(global-set-key(kbd "C-s") 'save-buffer)
(global-set-key(kbd "C-S-s") 'write-file)
(global-set-key(kbd "C-r") 'revert-buffer)
(global-set-key(kbd "C-a") 'mark-whole-buffer)
(global-set-key(kbd "M-'") 'comment-or-uncomment-region)
(global-set-key(kbd "C-o") 'dired)
(global-set-key(kbd "C-n") 'xah-new-empty-buffer)
(global-set-key(kbd "C-+") 'text-scale-increase)
(global-set-key(kbd "C--") 'text-scale-decrease)
;; Buffers and windows
(global-set-key(kbd "C-") 'next-buffer)
(global-set-key(kbd "C-") 'previous-buffer)
(global-set-key(kbd "C-") 'other-window)
(global-set-key(kbd "M-3") 'delete-other-windows)
(global-set-key(kbd "M-4") 'split-window-horizontally)
(global-set-key(kbd "M-5") 'split-window-vertically)
(global-set-key(kbd "M-6") 'balance-windows)
(global-set-key(kbd "C-f") 'isearch-forward)
(global-set-key(kbd "C-h") 'query-replace)
(global-set-key(kbd "C-S-h") 'query-replace-regexp)
(global-set-key(kbd "M-a") 'execute-extended-command)
(global-set-key(kbd "M-x") 'kill-whole-line)
(global-set-key(kbd "") 'keyboard-quit)
(when(get-buffer "*scratch*")
(kill-buffer "*scratch*"))
(fset 'yes-or-no-p 'y-or-n-p); ; ; Shortcuts for yea and no
;;; Format file before save
(defun format-current-buffer()
(indent-region (point-min) (point-max)))
(defun untabify-current-buffer()
(if (not indent-tabs-mode)
(untabify (point-min) (point-max)))
nil)
(add-to-list 'write-file-functions 'untabify-current-buffer)
(add-to-list 'write-file-functions 'delete-trailing-whitespace)
;;; САМЫЙ ВАЖНЫЙ МОМЕНТ - ВЫНЕСЕНИЕ НАСТРОЕК СРЕДЫ В settings.el и загрузка их оттуда
(setq custom-file "~/.emacs.d/settings.el")
(load-file "~/.emacs.d/settings.el")
;;; Теперь просто описание используемых пакетов
;;; Настройки в большинстве случаев подтягиваются из файла settings.el
(use-package airline-themes
:requires powerline
:init
(load-theme 'airline-molokai))
(use-package all-the-icons)
(use-package beacon
:diminish
:commands beacon-mode)
(use-package company
:diminish
:commands company-mode
:config
;; From https://github.com/company-mode/company-mode/issues/87
;; See also https://github.com/company-mode/company-mode/issues/123
(defadvice company-pseudo-tooltip-unless-just-one-frontend
(around only-show-tooltip-when-invoked activate)
(when (company-explicit-action-p)
ad-do-it))
(defun check-expansion ()
(save-excursion
(if (outline-on-heading-p t)
nil
(if (looking-at "\\_>") t
(backward-char 1)
(if (looking-at "\\.") t
(backward-char 1)
(if (looking-at "->") t nil))))))
(define-key company-mode-map [tab]
'(menu-item "maybe-company-expand" nil
:filter (lambda (&optional _)
(when (check-expansion)
#'company-complete-common))))
(eval-after-load "yasnippet"
'(progn
(defun company-mode/backend-with-yas (backend)
(if (and (listp backend) (member 'company-yasnippet backend))
backend
(append (if (consp backend) backend (list backend))
'(:with company-yasnippet))))
(setq company-backends
(mapcar #'company-mode/backend-with-yas company-backends))))
:init (global-company-mode t))
(use-package company-quickhelp
:bind
(:map company-active-map
("C-c h" . company-quickhelp-manual-begin)))
(use-package css-mode
:mode "\\.css\\'")
(use-package elpy
:mode "\\.py\\'"
:requires python-mode
:hook (add-hook 'before-save-hook #'elpy-format-code)
:init
(elpy-enable)
(defalias 'workon 'pyvenv-workon))
(use-package emmet-mode
:mode ("\\.html\\'" . emmet-mode)
:bind
("C-j" . emmet-expand-line))
(use-package flycheck
:commands flycheck-mode
:init(add-hook 'after-init-hook #'global-flycheck-mode))
(use-package highlight-numbers
:hook(prog-mode . highlight-numbers-mode))
(use-package ibuffer
:bind([f2] . ibuffer)
:init
(add-hook 'ibuffer-mode-hook #'(lambda ()(ibuffer-switch-to-saved-filter-groups "default"))))
(use-package js2-mode
:mode ("\\.js\\'" . js2-mode)
:requires flycheck
:bind(
:map js2-mode-map
("M-n" . flycheck-next-error)
("M-p" . flycheck-previous-error))
:config
(add-to-list 'flycheck-disabled-checkers #'javascript-jshint)
(flycheck-add-mode 'javascript-eslint 'js2-mode)
(flycheck-mode 1)
(js2-highlight-unused-variables-mode t))
(use-package json-mode
:mode (("\\.json\\'" . json-mode)
("\\.bowerrc\\'" . json-mode)
("\\.jshintrc\\'" . json-mode)))
(use-package json-reformat
:after json-mode)
(use-package magit
:bind([f5] . magit-status))
(use-package markdown-mode
:mode "\\.md\\'")
(use-package monokai-theme
:init(load-theme 'monokai))
(use-package neotree
:requires all-the-icons
:bind
([f8] . neotree-toggle))
(use-package powerline)
(use-package py-isort
:hook
(add-hook 'before-save-hook 'py-isort-before-save))
(use-package rainbow-delimiters
:hook
(prog-mode . rainbow-delimiters-mode))
(scroll-bar-mode -1)
(use-package tide
:requires js2-mode
:after js2-mode
:mode ("\\.js\\'" . tide-mode)
:hook((before-save-hook . tide-format-before-save)
(typescript-mode-hook . setup-tide-mode)))
(use-package web-beautify)
(use-package web-mode
:commands web-mode
:requires web-beautify
:mode("\\.phtml\\'" . web-mode)
("\\.html\\'" . web-mode)
:hook (add-hook 'before-save-hook 'web-beautify-html-buffer t t))
(use-package yasnippet
:after prog-mode
:defer 10
:diminish yas-minor-mode
:mode("/\\.emacs\\.d/snippets/" . snippet-mode)
:config
(yas-load-directory (expand-file-name "snippets" user-emacs-directory))
(yas-global-mode 1))
(use-package yasnippet-snippets
:after yasnippet)
;;; init.el ends here
Что интересного я взял у автора?
Во-первых, саму организацию хранения описания пакетов. Во-вторых, он отсортировал вызовы use-package по алфавиту. Быстрый поиск не нужен, если можно просто нажать пару раз [PgDn]. В-третьих, он и в файле настроек применил сортировку по алфавиту.
Для тех, кому интересен оригинальный конфиг, его можно найти здесь.
Настройка DNS-сервера bind9 в Debian/Astra Linux
Цели
- Настройка основного сервера DNS для маленькой локальной сети
- Сервер должен быть безопасным
- Сервер должен хранить настройки для конфигурации данной сети
- Сервер должен обслуживать доменную зону
home.netс адресами в подсети192.168.0/24
Как обычно, если не указано иное, команды выполняются от имени пользователя root.
Исходные данные
| Доменная зона | home.net |
| Подсеть | 192.168.0/24 |
| Имя основного сервера | dc.home.net |
| IP-адрес сервера имен | 192.168.0.1 |
| Имя первого хоста | arm01.home.net |
| IP-адрес первого хоста | 192.168.0.101 |
| Имя N-го хоста | armN.home.net |
| IP-адрес N-го хоста | 192.168.0.(100+N) |
Установка сервера
apt-get install bind9 -y
Сервер установлен, но установка сделана не безопасным способом. Нужно выполнить несколько дополнительных действий, описанных подробнее в Debian Wiki - Bind.
Будем запускать сервер в изолированном окружении:
mkdir -p /var/bind9/chroot/{etc,dev,var/cache/bind,var/run/named}
mknod /var/bind9/chroot/dev/null c 1 3
mknod /var/bind9/chroot/dev/random c 1 8
chmod 660 /var/bind9/chroot/dev/{null,random}
mv /etc/bind /var/bind9/chroot/etc
ln -s /var/bind9/chroot/etc/bind /etc/bind
chown bind:bind /var/bind9/chroot/etc/bind/rndc.key
chmod 775 /var/bind9/chroot/var/{cache/bind,run/named}
chgrp bind /var/bind9/chroot/var/{cache/bind,run/named}
Теперь нужно изменить расположение PIDFILE. Для этого в файле /etc/init.d/bind9 нужно переопределить переменную PIDFILE.
PIDFILE=/var/bind9/chroot/var/run/named/named.pid
Чтобы сервер понимал, что его запускают в изолированном окружении, нужно изменить параметры его запуска, внеся небольшие коррективы в файл /etc/default/bind9
OPTIONS="-u bind -t /var/bind9/chroot"
Перенастроим логирование rsyslog
echo "\$AddUnixListenSocket /var/bind9/chroot/dev/log" > /etc/rsyslog.d/bind-chroot.conf
Настройка опций сервера
Безопасность
Основные настройки сервера хранятся в файле /etc/bind/named.conf.options (на самом деле сейчас это всего лишь символическая ссылка, но на суть дела это не влияет). Добавим пару параметров для пущей безопасности в разделе options:
options {
...
version none; // Скроем версию bind
allow-query {
192.168.0/24; // Отвечать будем только на запросы, приходящие из внутренней сети
};
...
}
Включение в конфигурацию новой доменной зоны
В файле /etc/bind/named.conf.default-zones добавим указание на файлы прямой и обратной зоны, чтобы сервер мог обслуживать локальную сеть:
...
zone "home.net" in { // Локальная сеть
type master;
file "/etc/bind/db.home.net"; // В этом файле будут адреса прямой зоны
};
zone "0.168.192.in-addr.arpa" { // Так описывается обратная зона, т. е. первые три октета
// записываются в обратном порядке и добавляется .in-addr.arpa
type master;
file "/etc/bind/db.0.168.192"; // В этом файле будут адреса обратной зоны
};
Прямая доменная зона
Ниже просто приведу содержимое файла /etc/bind/db.home.net.
$TTL 3h
@ IN SOA dc.home.net. administrator.home.net. (
; Вместо @ будет подставлено автоматически имя зоны из файла /etc/bind/named.conf.default-zones
2017092701 ; Это число нужно менять каждый раз при изменении этого файла
; Очень удобно взять текущее число и добавить ещё пару цифр для указания ревизии
3h ;
1h ;
1w ;
1h
)
IN NS dc.home.net. ; Указываем имя основного DNS-сервера, обслуживающего зону
; Наличие пробела или табуляции в начале строки и точки
; после .net обязательно
dc IN A 192.168.0.1 ; IP-адрес сервера имен
imap IN CNAME dc ; Указываем, что наш DNS-сервер так же отзывается на imap.home.net
smtp IN CNAME dc ; и smtp.home.net
arm01 IN A 192.168.0.101
arm02 IN A 192.168.0.102
arm03 IN A 192.168.0.103
arm04 IN A 192.168.0.104
arm05 IN A 192.168.0.105
arm06 IN A 192.168.0.106
arm07 IN A 192.168.0.107
arm08 IN A 192.168.0.108
arm09 IN A 192.168.0.109
arm10 IN A 192.168.0.110
Обратная зона
Создадим файл, на который ссылается обратная зона, и заполним его по образцу:
$TTL 3h
@ IN SOA dc.home.net. administrator.home.net. (
2017092701 ; Это число тоже нужно менять
3h ;
1h ;
1w ;
1h
)
IN NS dc.home.net.
1 IN PTR dc.home.net. ; Наш сервер
101 IN PTR arm01.home.net.
102 IN PTR arm02.home.net.
103 IN PTR arm03.home.net.
104 IN PTR arm04.home.net.
105 IN PTR arm05.home.net.
106 IN PTR arm06.home.net.
107 IN PTR arm07.home.net.
108 IN PTR arm08.home.net.
109 IN PTR arm09.home.net.
110 IN PTR arm10.home.net.
Запуск сервера и проверка работоспособности
Если всё сделано правильно, точки расставлены и IP-адреса указаны верно, можно попробовать запустить наш сервер:
service bind9 start
Если вместо кучи ошибок сервер просто написал, что всё хорошо, можно проверить разрешение имен:
host arm01.home.net
host 192.168.0.9
В обоих случаях сервер должен вернуть информацию о том, на что указывает доменное имя или IP-адрес. Если вместо этого он выдает сообщение об ошибке, самое время проверить корректность конфигурационных файлов. Это делается вызовом следующих несложных команд:
named-checkconf /etc/bind/named.conf
named-checkzone home.net /etc/bind/db.home.net
named-checkzone 192.168.0 /etc/bind/db.0.168.192
Данные утилиты из состава пакета bind9utils укажут на ошибки в конфигурационных файлах.
Клиенты
Существует несколько способов настроить обращение к DNS-серверу на клиентских машинах. По скольку речь идет об операционной системе для социальной группы 'siloviki', выбор инструментальных средств невелик - wicd, /etc/network/interfaces и /etc/resolv.conf.
Первый способ отметаем сразу же, поскольку с wicd довольно много проблем. Не буду останавливаться на них подробно, но обычно первое, что приходится делать на свежеустановленной системе - убрать его из автозагрузки:
service wicd stop
chkconfig wicd off
Можно указать DNS-сервер в настройках сетевых интерфейсов, однако, в этом случае их нужно прописывать для каждого сетевого интерфейса, а я не люблю повторяться. В связи с этим просто откорректируем файл /etc/resolv.conf на клиентских машинах:
domain home.net
search home.net
nameserver 192.168.0.1
Работа в ненулевых мандатных режимах
В данном дистрибутиве реализована мандатная модель разграничения доступа, в том числе к сетевым сервисам. Чтобы обеспечить корректную работу демона named в режимах с мандатной меткой, отличной от нулевой, нужно добавить всего одну строчку в файл /etc/parsec/privsock.conf:
/usr/sbin/named
Управление пакетами в EMACS с помощью use-package
Что такое use-package и как с ним бороться.
Автор данного пакета преследовал цель удобного управления своими пакетами, поддержание чистоты конфигурационных файлов EMACS и по возможности оптимизацию запуска. Ему удалось их успешно решить, а я решил воспользоваться результатами чуждого труда и заодно поделиться информацией. Почитать на англиском про use-package можно здесь, а в статье я лишь оставлю заметку о том, что реально пригодилось.
~/.emacs
Мой файл .emacs содержит довольно мало строк: установщик некоторых базовых пакетов, загрузчик файлов конфигурации, немного комментариев. Выглядит это всё так:
;;; package --- Summary
;;; Commentary:
;;; Main EMACS settings file, load settings from parts.
;;; Code:
(require 'package)
;;; Источники для установки пакетов. Дело в том, что MELPA Stable
;;; содержит не очень свежие версии, поэтому иногда лучше ставить
;;; пакеты из основного репозитория.
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/"))
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(setq package-enable-at-startup nil)
(package-initialize nil)
;;; Если пакет use-package не установлен, его нужно скачать и
;;; установить
(unless (package-installed-p 'use-package)
(message "EMACS install use-package.el")
(package-refresh-contents)
(package-install 'use-package))
;;; Установили, загрузили, указали, что недостающие пакеты нужно
;;; автоматически загружать и устанавливать.
(require 'use-package)
(setq use-package-always-ensure t)
;;; Указываем откуда брать части настроек.
(defconst user-init-dir
(cond ((boundp 'user-emacs-directory) user-emacs-directory)
((boundp 'user-init-directory) user-init-directory)
(t "~/.emacs.d/")))
;;; Функция для загрузки настроек из указанного файла.
(defun load-user-file (file)
(interactive "f")
"Load a file in current user's configuration directory"
(load-file (expand-file-name file user-init-dir)))
;;; Части конфигурации. Порядок не имеет принципиального значения,
;;; однако я рекомендую некоторые базовые вещи помещать в начало,
;;; чтобы не было необходимости вспоминать базовые команды EMACS
;;; если в результате улучшения сломается один из базовых конфигов.
(load-user-file "neotree.el")
(load-user-file "personal.el")
(load-user-file "themes.el")
(load-user-file "flycheck.el")
(load-user-file "company.el")
(load-user-file "ibuffer.el")
(load-user-file "python.el")
(load-user-file "web.el")
(load-user-file "javascript.el")
(load-user-file "markdown.el")
(load-user-file "json.el")
(load-user-file "yasnippet.el")
(load-user-file "helm.el")
(load-user-file "keyboard.el")
(load-user-file "fonts.el")
(load-user-file "powerline.el")
(load-user-file "elisp.el")
;;; А здесь EMACS хранит настройки, задаваемые через customize
(setq custom-file "~/.emacs.d/customize.el")
(load-user-file "customize.el")
;;; .emacs ends here
Половина дела сделана. Настройки размещены в разных файлах, каждый из которых не зависит от других. Вот теперь заживём!
neotree.el
;;; Package --- Summary
;;; Commentary:
;;; NeoTree - sidebar for file browsing
;;; Code:
;;; Как я и говорил, пакет будет скачан и установлен автоматически.
(use-package
neotree
:bind ([f8] . neotree-toggle) ;;; Так делается привязка клавиш.
:init (setq neo-window-width 35) ;;; Настройки ДО загрузки пакета.
:config (setq neo-smart-open nil)) ;;; Настройки ПОСЛЕ загрузки пакета.
;;; neotree.el ends here
Полагаю, данный пример наглядно показывает, как пользоваться use-package. Продолжим.
personal.el
;;; Package --- Summary
;;; Commentary:
;;; User settings for .emacs
;;; Code:
;;; Закрывать *scratch* при запуске.
(kill-buffer "*scratch*")
;;; Цветные скобочки
(use-package
rainbow-delimiters
:init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
(setq rainbow-delimiters-max-face-count 9))
;;; Scrolling
(setq scroll-step 1) ;; one line
(setq scroll-margin 10) ;; scroll buffer to 10 lines at going to last line
(setq scroll-conservatively 10000)
(setq directory-free-space-args "-Pm")
;; Подсветка результатов поиска и всё такое
(setq search-highlight t)
(setq query-replace-highlight t)
(setq column-number-mode 1) ;; Номера строк слева
(setq use-dialog-box nil) ;; Не нужны нам диалоги, будем всё руками делать
(auto-fill-mode -1) ;; Не знаю, что за параметр, так и не разобрался
(setq-default tab-width 4) ;; Заменить TAB на 4 пробела
(setq-default standart-indent 4) ;; Стандартный отступ - 4 пробела
(setq backup-inhibited t) ;; Backup'ы тоже делать не будем
(setq auto-save-default nil) ;; Автосохранение не нужно
(setq scroll-preserve-screen-position 10) ;; Показывать не менее 10 строк на экране
(setq-default c-basic-offset 4 c-indent-level 4 indent-tabs-mode nil) ;; TAB'ы не нужны
(setq-default save-place t) ;; Помнить, где был курсор в прошлый раз
;;; Нажатие Insert больше не включает режим замены
(define-key global-map [(insert)] nil)
;;; Автоформатирование перед сохранением
(defun format-current-buffer()
(indent-region (point-min)
(point-max)))
(defun untabify-current-buffer()
(if (not indent-tabs-mode)
(untabify (point-min)
(point-max)))
nil)
(add-to-list 'write-file-functions 'untabify-current-buffer)
(add-to-list 'write-file-functions 'delete-trailing-whitespace)
(cua-mode 1) ;;; Ctrl+C, Ctrl+V! Прямо как в Windows!
(desktop-save-mode 1) ;;; Помнить, какие файлы были открыты в прошлый раз
(fset 'yes-or-no-p 'y-or-n-p) ;;; Вместо yes и no понимать y и n
(global-hl-line-mode 1) ;;; Подсветка текущей строки
(global-linum-mode 1) ;;; Показывать номера строк всегда
(menu-bar-mode -1) ;;; А меню - никогда
(scroll-bar-mode -1) ;;; Скроллбар не нужен
(tool-bar-mode -1) ;;; Тулбар не нужен
;;; Умные скобочки
(use-package
smartparens
:config (smartparens-global-mode 1))
;; Electric pair mode
(electric-pair-mode 1)
;; Иконки в статус-баре
(use-package
mode-icons
:config (mode-icons-mode 1))
;; Показывать отступы во всех режимах
(use-package
indent-guide
:config (indent-guide-global-mode 1))
;;; Дерево отмены
(use-package
undo-tree
:config (global-undo-tree-mode 1))
;;; personal.el ends here
python.el
Очень интересный конфиг получается для Python.
;;; Package --- Summary
;;; Commentary:
;;; Settings for Python
;;; Code:
(defun annotate-pdb()
(interactive)
(highlight-lines-matching-regexp "import ipdb")
(highlight-lines-matching-regexp "import pdb")
(highlight-lines-matching-regexp "set_trace()")
(highlight-regexp "^TODO ")
(highlight-phrase "FIXME"))
(use-package
python
:mode ("\\.py'" . python-mode)
:init (progn
(defalias 'python2-mode 'python-mode)
(defalias 'python3-mode 'python-mod))
:config (setq-default py-separator-char 47) ;; Use spaces instead tab
(setq-default python-indent-offset 4) ;; 4 spaces instead 2 for python-mode
)
(use-package
company-anaconda
:ensure t
:init (add-to-list 'company-backends 'company-anaconda))
(use-package
py-autopep8
:init (progn (add-hook 'python-mode-hook 'py-autopep8-enable-on-save)))
(use-package
anaconda-mode
:commands anaconda-mode
:diminish anaconda-mode
:init (progn (add-hook 'python-mode-hook 'anaconda-mode)
(add-hook 'python-mode-hook 'eldoc-mode)
(add-hook 'python-mode-hook 'annotate-pdb)))
(use-package
pyvenv
:config (defalias 'workon 'pyvenv-workon))
(use-package
py-isort
:config (setq py-isort-options '("-sl"))
:init (progn (add-hook 'python-mode-hook 'py-isort-before-save)))
(use-package
company-anaconda
:config (add-to-list 'company-backends 'company-anaconda))
;;; python.el ends here
Не уверен, что нужно что-то тут объяснять, но на всякий случай свой company.el тоже выставляю напоказ.
company.el
Этот модуль отвечает за подсказки и автозавершение. Он новее, чем autocomplete, и активно развивается. Большая часть плагинов дополнения сейчас пишется именно под него.
;;; Package --- Summary
;;; Commentary:
;;; Settings for company
;;; Code:
(use-package
company
:diminish company-mode
:config (setq company-backends (remove 'company-ropemacs company-backends) company-tooltip-limit
20 company-tooltip-align-annotations t)
(global-company-mode 1))
;;; company.el ends here
Настройка сети в Astra Linux
Astra Linux использует для конфигурирования сетей собственную утилиту wicd. В общем, она довольно удобна, но у неё есть фатальный недостаток - её писали не мы сеть не будет работать до авторизации пользователя в системе. Для обычных компьютеров в этом нет ничего страшного, однако, для сервера это большая проблема, так как иногда его приходится перезагружать по SSH.
Пусть компьютеры будут находиться в сети с адресами 192.168.0.XXX, где вместо XXX - число от 1 до 254.
Настройка осуществляется путем правки файла /etc/network/interfaces. Каждый сетевой интерфейс (сетевая карта, хотя это не совсем точное название) настраивается отдельно. Настройки для сервера выглядят так:
auto lo eth0
iface lo inet loopback
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.1 # В качестве шлюза - наш сервер с IP=1
network 192.168.0.0 # Указываем сеть, это обязательно для работы в составе ALD
broadcast 192.168.0.255 # Сервер ALD начиная с Astra 1.5 выводит ошибку, если не видит
# этого параметра в настройках сети.
dns-nameservers 192.168.0.1 # Тут через пробел можно перечислить ВСЕ DNS-серверы сети
dns-search DOMAIN.NET # Имя домена ALD
Первая строчка auto lo eth0 указывает, какие интерфейсы должны быть запущены при загрузке ОС. Отмечу, что локальная петля lo должна присутствовать там в любом случае.
Пропустим описание локальной петли и сразу перейдем к сетевому интерфейсу.
iface |
Ключевое слово, говорящее о том, что дальше будет описание сетевого интерфейса |
eth0 |
Указываем, что данный сетевой интерфейс должен быть привязан к сетевой карте eth0. Посмотреть список карт можно командой: lshw -class network |
inet |
Указываем, что это будет настройка сети. |
static |
При этом все настройки будут указаны вручную. |
address |
IPv4-адрес компьютера |
netmask |
Маска подсети. |
gateway |
Шлюз, т. е. IP-адрес, через который идёт подключение к интернету. Обычно на сервере указывают адрес, выданный провайдером, но в нашем случае (закрытый от мира сегмент) пусть будет 192.168.150.1, т. е. компьютер обращается сам к себе. |
dns-nameservers |
Список разделенных пробелами IP-адресов DNS-серверов. Полезно при разворачивании ЕПП под управлением Astra Linux и настройке приложения bind. |
На клиентских компьютерах настройки следует выполнить аналогичным образом, меняя только четвёртый октет в поле address.
На этом настройка не заканчивается. Теперь нужно отключить автозапуск встроенных утилит и остановить уже запущенный экземпляр службы wicd, после чего перезапустить службу поддержки сети.
service wicd stop
chkconfig wicd off
rm /etc/xdg/autostart/fly-admin-wicd.desktop
service networking restart
Если на одной сетевой карте по каким-то причинам нужно иметь 2 или более IP-адресов, настройки делаются следующим образом:
auto lo
iface lo inet loopback # Кстати, удалять интерфейс локальной петли не стоит,
# некоторые службы от этого сходят с ума и начинают
# выдавать весьма странные ошибки
auto eth0:0
allow-hotplug eth0:0
iface eth0:0 inet static
address 192.168.0.1
netmask 255.255.255.0
network 192.168.0.0
gateway 192.168.0.1
broadcast 192.168.0.255
dns-nameservers 192.168.0.1 192.168.0.2
dns-search DOMAIN.NET
auto eth0:1
allow-hotplug eth0:1
iface eth0:1 inet static
address 10.2.12.54 # Адрес, маска и все остальные параметры в этой
netmask 255.255.255.128 # секции были придуманы за 20 секунд, поэтому
network 10.2.12.0 # не ручаюсь за правильность заполнения. Гуглите
gateway 10.2.12.1 # маску подсети для этого случая самостоятельно.
broadcast 10.2.12.255
dns-nameservers 8.8.8.8
dns-search GOOGLE.RU
Посмотреть настройку сети в Debian более подробно можно на официальной Wiki-странице или её несколько устаревшей русской версии
Хоткеи в EMACS
Основы
Я долгое время пользовался пакетом ergoemacs и был доволен, однако, со временем он стал обрастать функциями, которые мне стали не нужны, а иногда откровенно глючили на моём самосборном EMACS'е. Пришлось изучить, как настраиваются хоткеи в редакторе.
Во-первых, вместо привычных Ctrl, Alt и Shift в EMACS для обозначения модификаторов используются другие значения:
| C | Ctrl |
| M | Alt |
| S | Shift |
Ни в одном руководстве по EMACS вы не найдете записи типа Ctrl+S - там будет написано C-S, хотя по сути эти две записи идентичны.
Во-вторых, клавиши, которые нажимаются вместе, записываются через дефис.
Третье, регистр имеет значение.
Последнее, что нужно знать о клавиатурных комбинациях EMACS - некоторые команды состоят из последовательного нажатия разных клавиатурных комбинаций, например, выход из редактора выглядит так: C-x C-c, что означает следующее:
- Сначала нажимаем
Ctrl+X - Теперь нажимаем
Ctrl+C
Так же команда выхода из редактора требует подтверждения, если имеются модифицированные буферы, но об этом я напишу в другой раз.
К делу!
Перед тем, как использовать какую-либо клавиатурную комбинацию, следует убедиться, что она уже не привязана к какому-либо действию, либо освободить её от этой привязки. Ниже показано, как удалить привязку команды к комбинации и тут же связать её с новой командой:
(global-unset-key (kbd "C-S-c C-S-c"))
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
С простыми клавишами разобрались, добавим функциональные:
(require 'neotree)
(require 'ibuffer)
(require 'magit)
(require 'dired)
(global-set-key [f2] 'ibuffer)
(global-set-key [f3] 'dired)
(global-set-key [f8] 'neotree-toggle)
(global-set-key [f10] 'magit-status)
Теперь посмотрим, как описываются стрелки:
;; Resize windows
(global-set-key (kbd "S-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "S-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "S-C-<down>") 'shrink-window)
(global-set-key (kbd "S-C-<up>") 'enlarge-window)
Можно ли сделать с полученными знаниями что-то полезное? Да! Давайте удалим ergoemacs и начнем вместо него использовать свои собственные комбинации!
;;; Package --- Summary
;;; Commentary:
;;; Keybindings for non-latin layout
;;; Code:
(setq initial-major-mode (quote text-mode))
(defun cfg:reverse-input-method (input-method)
"Build the reverse mapping of single letters from INPUT-METHOD."
(interactive
(list (read-input-method-name "Use input method (default current): ")))
(if (and input-method (symbolp input-method))
(setq input-method (symbol-name input-method)))
(let ((current current-input-method)
(modifiers '(nil (control) (meta) (control meta))))
(when input-method
(activate-input-method input-method))
(when (and current-input-method quail-keyboard-layout)
(dolist (map (cdr (quail-map)))
(let* ((to (car map))
(from (quail-get-translation
(cadr map) (char-to-string to) 1)))
(when (and (characterp from) (characterp to))
(dolist (mod modifiers)
(define-key local-function-key-map
(vector (append mod (list from)))
(vector (append mod (list to)))))))))
(when input-method
(activate-input-method current))))
(cfg:reverse-input-method 'russian-computer)
(require 'neotree)
(require 'ibuffer)
(require 'magit)
(require 'dired)
(global-set-key [f2] 'ibuffer)
(global-set-key [f3] 'dired)
(global-set-key [f8] 'neotree-toggle)
(global-set-key [f10] 'magit-status)
;; Multiple cursors
(global-unset-key (kbd "C-S-c C-S-c"))
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
;; Resize windows
(global-set-key (kbd "S-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "S-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "S-C-<down>") 'shrink-window)
(global-set-key (kbd "S-C-<up>") 'enlarge-window)
(defun xah-new-empty-buffer ()
"Open a new empty buffer.
URL `http://ergoemacs.org/emacs/emacs_new_empty_buffer.html'
Version 2015-06-12"
(interactive)
(let ((ξbuf (generate-new-buffer "untitled")))
(switch-to-buffer ξbuf)
(funcall (and initial-major-mode))
(setq buffer-offer-save t)))
;; Save/close/open
(global-set-key (kbd "C-w") 'kill-this-buffer)
(global-set-key (kbd "C-s") 'save-buffer)
(global-set-key (kbd "C-S-s") 'write-file)
(global-set-key (kbd "C-r") 'revert-buffer)
(global-set-key (kbd "C-a") 'mark-whole-buffer)
(global-set-key (kbd "M-'") 'comment-or-uncomment-region)
(global-set-key (kbd "C-o") 'dired)
(global-set-key (kbd "C-n") 'xah-new-empty-buffer)
(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
;; Buffers and windows
(global-set-key (kbd "C-<next>") 'next-buffer)
(global-set-key (kbd "C-<prior>") 'previous-buffer)
(global-set-key (kbd "C-<tab>") 'other-window)
(global-set-key (kbd "M-3") 'delete-other-windows)
(global-set-key (kbd "M-4") 'split-window-horizontally)
(global-set-key (kbd "M-5") 'split-window-vertically)
(global-set-key (kbd "M-6") 'balance-windows)
(global-set-key (kbd "C-f") 'isearch-forward)
(global-set-key (kbd "C-h") 'query-replace)
(global-set-key (kbd "C-S-h") 'query-replace-regexp)
(global-set-key (kbd "M-a") 'execute-extended-command)
(global-set-key (kbd "M-x") 'kill-whole-line)
(global-set-key (kbd "<esc>") 'keyboard-quit)
(setq x-select-enable-clipboard t)
;; Highlight search resaults
(setq search-highlight t)
(setq query-replace-highlight t)
;;; keyboard.el ends here
У меня конфигурация разбита на несколько маленьких файлов, и я привёл целиком содержимое keyboard.el. Полагаю, не проблема выбросить ненужное и оставить нужное. Большая часть команд будет работать без установки дополнительных пакетов.
Django 1.8, Python 3, WSGI и Gunicorn
Введение
В данной статье рассказывается, как можно запустить приложение на Django и Python 3 под WSGI. Способ не претендует на звание самого лучшего, замечания по настройке и прочим нюансам приветствуются.
Структура каталогов
Следует создать в каталоге /var/www подкаталог для нашего проекта. Пусть сегодня он будет называться talos. В нём нужно будет создать каталоги для размещения статичных файлов, файлов, загружаемых пользователями, и логов.
cd /var/www
mkdir talos
cd talos/
mkdir static media log
Сам проект будет расположен в виртуальном окружении, которое будет создано чуть позже.
Создание файла запуска
Здесь же, в каталоге /var/www/talos, создадим файл run.bash, который будет запускать приложение, передавая ему нужные параметры.
#!/bin/bash
NAME="talos" # Название приложения
DJANGODIR=/var/www/.virtualenvs/talos/talos # Директорая проекта - путь к виртуальному окружению
# плюс папка с проектом
SOCKFILE=/var/www/sockets/talos.sock # Тут будет лежать сокет
USER=www-data # От чьего имени запускается
GROUP=www-data # Группа для запуска
NUM_WORKERS=3 # Кол-во воркеров, обычно число ядер * 2 + 1
DJANGO_SETTINGS_MODULE=talos.settings # Откуда брать настройки
DJANGO_WSGI_MODULE=talos.wsgi # Имя wsgi-файла для запуска
echo "Starting $NAME as `whoami`"
# Активация окружения
cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Если папки для сокета нет, её надо создать
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Запуск через gunicorn с передачей параметров
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=/var/www/talos/log/talos.log
Создание виртуального окружения
Последние версии Django написаны на Python 3, да и вообще использовать Python 2 в 2015 году - дурной тон. Ставим нужные пакеты, если их ещё нет:
apt-get install python3-dev virtualenvwrapper -y
Первый пакет нужен для сборки пакетов, поставляемых в исходных кодах (lxml, psycopg2, pillow), второй - для удобного управления виртуальными окружениями. Пакеты установлены, пользователь www-data в системе. Пришло время создать окружение и поставить нужные пакеты:
mkvirtualenv talos --python=/usr/bin/python3
workon talos
В результате в каталоге для виртуальных окружений (у каждого пользователя свой, по умолчанию называется .virtualenvs) будет создан подкаталог talos. В нём будут размещены необходимые для работы с окружением скрипты и несколько других каталогов. Разместим наш проект внутри каталога /var/www/.virtualenvs/talos.
Далее следует поставить в окружение все необходимые пакеты, требуемые для запуска проекта, а так же пакет gunicorn. При необходимости стоит так же обновить pip, его последние версии умеют кэшировать скачанные пакеты.
Не забудьте создать статику и при необходимости подкорректировать файл настроек приложения.
Запуск через supervisor
Если supervisor ещё не установлен, пришло время это сделать:
apt-get install supervisor -y
Настройки хранятся в каталоге /etc/supervisor. Главный файл называется supervisor.conf, файлы для запуска приложений следует расположить в каталоге /etc/supervisor/conf.d/, указав расширение .conf. В нашем случае файл будет лежать по пути /etc/supervisor/conf.d/talos.conf
[program:talos]
command=/var/www/talos/run.bash
user=www-data
group=www-data
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/talos/log/supervisor.log
Когда файл будет создан, следует обновить данные Supervisor'а:
supervisorctl update
При необходимости перезапустить то или иное приложение следует вызывать не перезапуск системной службы supervisor, а давать команды supervisorctl:
supervisorctl update # Перечитать файлы конфигации приложений
supervisorctl start talos # Запустить приложение talos
supervosorctl stop talos # Остановить приложение talos
supervisorctl restart talos # Перезапуск приложения talos
supervisorctl status # Посмотреть статус всех приложений
supervisorctl ДЕЙСТВИЕ all # Выполнить ДЕЙСТВИЕ со всеми приложениями, например, перезапуск
Если всё сделано правильно, приложение будет запущено, а в каталоге /var/www/sockets/ появится файл сокета talos.sock (как было настроено в файле run.bash).
Подключение к nginx
Всё, что нужно теперь сделать - указать nginx путь к сокету и откуда брать статику для проекта. В общем-то, всё довольно просто. Nginx лучше ставить из официального репозитория проекта, а не из Debian'овского, там пакет не обновляется годами.
apt-get install nginx -y
Все настройки в каталоге /etc/nginx, главный файл - nginx.conf, настройки для сайтов в .conf-файлах, лежащих в каталоге /etc/nginx/conf.d/.
Создадим файл настроек, общих для всех сайтов: /etc/nginx/proxy_params.conf:
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 20m;
client_body_buffer_size 1m;
proxy_buffering off;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_connect_timeout 180;
proxy_buffer_size 4k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 1m;
add_header X-Frame-Options "SAMEORIGIN";Возможно, данные настройки придётся доработать исходя из реальной конфигурации сервера. Здесь я на этом останавливаться не буду. Переходим к созданию файла конфигурации для нашего проекта:
upstream talos {
server unix:/var/www/sockets/talos.sock fail_timeout=0;
keepalive 30;
}
server {
listen 80;
server_name talos.lo;
keepalive_timeout 3;
access_log off;
error_log /var/www/talos/log/nginx_error.log crit;
location / {
proxy_pass http://talos/;
include /etc/nginx/proxy_params.conf;
}
location /static/ {
alias /var/www/talos/static/;
expires 3d;
}
location /media/ {
alias /var/www/talos/media/;
expires 3d;
}
location ~* \.(7z|jpg|jpeg|gif|png|ico|css|bmp|swf|js|html|txt|doc|docx|pdf|rar|xls|xlsx|zip)$ {
root /var/www/talos/;
expires 3d;
add_header Cache-Control: public;
access_log off;
error_log /var/www/talos/log/nginx_static_error.log;
}
}
Перезапустите nginx, тобы он подхватил новый конфигурационный файл. На этом всё.
Минимальная настройка SSH в Debian 7 Wheezy
Цели
В этой статье я расскажу о минимальных настройках, необходимых для того, чтобы на вашем сервере заработала служба OpenSSH, позволяющая удалённо подключаться к нашей машине и выполнять нужные команды. Кроме того, будут рассмотрены вопросы использования ключей для доступа к серверу.
Установка пакетов
Установить сервер OpenSSH в Debian очень просто:
apt-get install openssh-server -y
Вместе с самим сервером ставится несколько зависимостей. В моём случае (Debian 7.5) это openssh-client и ncurses-term.
Служба сервера sshd будет автоматически запущена после установки. Обращаться к ней в терминале следует по имени ssh, например (запуск, остановка, перезапуск):
service ssh start
service ssh stop
service ssh restart
Увеличение длины серверного ключа
До того, как приступить к изменению основных настроек OpenSSH, следует сгенерировать более длинные серверные ключи, иначе безопасность будет под угрозой. Делается это очень просто:
- Переходим в каталог
/etc/ssh - Изменяем в sshd_config значение параметра
ServerKeyBitsс 768 на 2048. Удаляем старые ключи командой
rm -rf ssh_host_*Выполняем перегенерацию ключей сервера (служба будет перезапущена автоматически):
dpkg-reconfigure openssh-server
Минимальная настройка
Все найстроки сервера OpenSSH хранятся в файле /etc/ssh/sshd_config. Откроем его для редактирования и рассмотрим минимально необходимые опции, которые не рекомендуется трогать либо наоборот настоятельно рекомендуется изменить.
Port 22- лучше всего сразу сменить порт на другой, однако, номер порта желательно выбрать больше 1024, чтобы случайно не создать конфликт с какой-нибудь другой программой, работающей на этом порту.ListenAddress 0.0.0.0- по умолчанию закомментировано. Можно указать, какой интерфейс должен слушать наш сервер. Если на сервере несколько интерфейсов, один из которых торчин наружу, например, предоставляет доступ к WEB-серверу, а работа с сервером будет производиться только из внутренней сети, я советую указать здесь адрес сервера во внутренней сети, чтобы заблокировать доступ из Интернета.UsePrivilegeSeparation yes- ни в коем случае не отключать разделение привилегий!LoginGraceTime 120- время в секундах, в течение которого следует авторизоваться на сервере. По истечении указанного интервала сервер автоматически разорвёт соединение.PermitRootLogin yes- настоятельно рекомендую сменить наno! Пользовательrootне должен подключаться к серверу! Для выполнения команд, требующих повышения привилегий, следует использоватьsudo!PubkeyAuthentication yes- включаем, т.к. дальше будет рассматриваться использование публичных ключей для подключения к серверу.AuthorizedKeysFile %h/.ssh/authorized_keys- следует раскомментировать для доступа с помощью открытых ключей шифрования. По умолчанию эта настройка указывает на то, что открытые ключи каждого пользователя следует искать в его домашнем каталоге, в файлеauthorized_keys, лежащем в подкаталоге.ssh.
Изменив эти минимальные настройки, перезапустите службу ssh.
Проверка работоспособности
Попробуйте подключиться к своему серверу с него самого:
ssh user@localhost
где user - ваш настоящий логин в системе.
При самом первом подключении ваш SSH-клиент будет спрашивать, следует ли доверять указанному хосту и принять от него ключ шифрования. Отвечаем yes (нужно написать слово полностью). Сервер предложит ввести пароль для авторизации в системе. Вводим его. Если всё правильно, вы окажетесь в консоли, где сможете вводить команды.
Генерация и размещение ключей
Генерация ключей
При шифровании с открытым ключом потребуется создать пару из двух ключей - открытого и закрытого. В *nix-системах стандартным средством для их генерации является программа ssh-keygen. Запуск её с различными параметрами приводит к созданию различных ключей. В нашем случае будет использован минимум настроек.
Выполните указанную ниже команду для создания ключа длиной 2048 бит и с комментарием "New generated key". Права root не требуются. Я советую добавить комментарий для ключа - в этом случае при подключении с его помощью в логах сервера будет отображаться этот комментарий. Можете ввести сюда свои имя и фамилию.
ssh-keygen -b 2048 -C "New generated key"
Система предложит указать имя для новых файлов. Для примера будем использовать new_key
Затем будет задан вопрос, какая парольная фраза будет использоваться для ключа. Если не заполнять это поле, то ключ не будет защищён паролем. Рекомендую ввести сюда что-нибудь. После первого ввода парольной фразы будет предложено ввести её ещё раз.
После этого в текущем каталоге (если вы ввели имя файла выше) будут созданы два файла - new_key и new_key.pub
Файл new_key - это закрытый ключ. Его нужно сохранить в надёжное место на вашем компьютере и не давать никому. Как правило, его кладут в домашнем каталоге в папку .ssh под именем id_rsa, при этом права на файл должны быть
mv new_key ~/.ssh/id_rsa
chmod 0600 ~/.ssh/id_rsa
Если права будут указаны неправильно, могут возникнуть проблемы. Например, утилита Seahorse из комплекта Gnome при попытке добавить этот ключ в хранилище будет запрашивать пароль, но при нажатии кнопки "Сохранить" выдаст ошибку.
Файл new_key.pub - это открытый ключ. Его также следует сохранить на вашем компьютере, однако, именно его следует распространять на серверах, к которым вы будете подключаться.
Размещение ключей на целевой системе
Если в домашнем каталоге пользователя не существует каталога .ssh, создайте его, а внутри него разместите пустой файл authorized_keys.
cd ~
mkdir .ssh
cd .ssh/
touch authorized_keys
Теперь в этот файл мы добавим наш открытый ключ с помощью стандартной команды >>
cat ~/new_key.pub >> authorized_keys
Теперь следует скопировать закрытый ключ на ваш компьютер. Его мы будем использовать для подключения к нашему серверу.
Использование закрытых ключей и Putty
Формат закрытых ключей, используемых программой Putty, несколько отличается от того, который используется в *nix-системах. Тем не менее, в комплекте идёт программа puttygen. Запустите её.
В меню выберите пункт Conversion, а в нём - Import key.
Найдите ваш закрытый ключ и откройте его.
Если ранее вы указали парольную фразу, сейчас её нужно будет ввести для открытия ключа.
Нажмите кнопку Save private key
Дайте подходящее имя закрытому ключу и сохраните его куда-нибудь. Как видите, формат файла изменился - теперь он ppk
Создайте в Putty новое подключение. В настройках найдите пункт Auth. На этой странице в поле Private key file for authentication выберите сохранённый ключ.
Сохраните подключение.
Нажмите Open
Теперь при подключении вам нужно будет вводить не пароль пользователя системы, а пароль от вашего ключа. Удобство заключается в том, что можно создать один публичный ключ и разместить его на десятке серверов. Теперь вместо того, чтобы помнить 10 разных паролей, достаточно помнить всего один и хранить его и секретный ключ в надёжном месте, исключающем доступ посторонних лиц.
Использование ключей для авторизации не отменяет ввода пароля пользователя при вызове команды sudo!
Настройка Redmine на Debian 7
Установка и настройка Redmine в Debian 7 (nginx + postgresql + thin)
В данной статье рассматривается установка и настройка Redmine версии 1.x в Debian 7 с помощью apt. Если вам нужна инструкция по настройке Redmine версии 2.x, то эта статья не для вас.
Краткое содержание:
- Введение
- Список используемых пакетов.
- Порядок установки и настройки пакетов.
- Предварительная настройка PostgreSQL
- Установка пакетов
- Создание базы данных
- Увязка Redmine с nginx через thin.
Введение
Redmine - система для управления проектами. Если говорить простым языком, эта система служит для того, чтобы можно было вести учёт обращений, заявок, багрепортов и известных проблем о каждом продукте компании. Помимо этого в системе есть встроенная Wiki, база знаний, диаграммы Ганта, разделение по проектам и ролям и т.д. Если вы работаете в фирме, которая занимается разработкой ПО, то этот или аналогичный продукт вам жизненно необходим. С помощью Redmine можно оперативно отслеживать ход работы, исправления обнаруженных ошибок и т.д. В общем, на выходе получается целый комбайн.
Список используемых пакетов
Для работы Redmine требуется установка Ruby On Rails. К нашему удовольствию разработчики Debian'а включили все необходимые пакеты в список зависимостей, значительно упростив установку. Исключение сделано лишь для двух пакетов - сервер, который будет запускать Redmine, и пакет для соединения с БД.
Ниже приведён минимальный список пакетов, которые нам потребуются:
thin- сервер для запуска продуктов, написанных на Rubyredmine- сама системаruby-pg- драйвер для подключения программ, написанных на Ruby On Rails, к СУБД PostgreSQL.
Установка Ruby будет выполнена автоматически
Предварительная настройка базы в PostgreSQL
Запустим интерпретатор psql от имени суперпользователя postgres:
sudo su -c psql postgres
Создадим нового пользователя и базу данных, к которой он будет иметь полный доступ, после чего закроем интерпретатор:
CREATE ROLE redmine WITH PASSWORD 'redmine' LOGIN;
CREATE DATABASE redmine WITH OWNER redmine;
\q
Естественно, вы можете дать пользователю и базе любое нужное имя. Кроме того, на одном сервере можно развернуть несколько экземпляров Redmine - для этого нужно будет создать несколько баз (и, возможно, пользователей) и настроить несколько конфигураций для thin, но я сейчас этого делать не буду.
Установка пакетов и настройка параметров Redmine
Установка пакетов
Для установки всех необходимых пакетов нужно от имени root выполнить команду:
apt-get install redmine ruby-pg thin -y
Во время установки менеджер пакетов предложит настроить базу данных. Отвечаем отрицательно. Базу данных лучше настраивать через правку конфигурационных файлов, т.к. установщик Redmine предлагает дать ему административный доступ к PostgreSQL.
Настройка доступа к БД
Перейдём в каталог /etc/redmine/default
cd /etc/redmine/default
Здесь находится всего два файла - database.yml и session.yml. Нам нужен только первый, отвечающий за настройки доступа к БД.
Содержимое database.yml:
production:
adapter: postgresql
database: redmine
host: localhost
port:
username: redmine
password: redmine
encoding: utf8
Все настройки, полагаю, понятны без комментариев. Отмечу только, что первая строка, production:, указывает на то, что данная конфигурация должна использоваться при запуске сервера в рабочем режиме. Также доступны режимы development и test.
Настройка сервера thin
Теперь нужно настроить thin. В Debian 7 при установке thin ставятся сразу две его версии, 1.8 и 1.9.1, мы будем использовать последнюю. Переходим в каталог настроек и создаём файл для запуска Redmine:
cd /etc/thin1.9.1/
touch redmine.yml
chmod 644 redmine.yml
Открываем созданный файл в любимом текстовом редакторе и вносим туда следующие данные:
---
chdir: /usr/share/redmine
environment: production
timeout: 30
log: /var/log/thin/redmine.log
pid: /var/run/redmine/redmine.pid
max_conns: 1024
max_persistent_conns: 512
require: []
wait: 30
socket: /var/run/redmine/redmine.sock
daemonize: true
user: www-data
group: www-data
servers: 1
prefix: /redmine
socket указывает путь и имя сокетов, создаваемых thin при запуске Redmine.
Параметр servers указывает, сколько серверов следует запустить. Другими словами, он определяет количество сокетов, которые будут созданы в указанном каталоге. К имени сокета, указанному выше, будет добавлен порядковый номер.
Servers: 1
ls /var/run/redmine
redmine.sock.0
Servers: 2
ls /var/run/redmine
redmine.sock.0
redmine.sock.1
prefix указывает на то, по какому адресу на сервере будут обрабатываться запросы к Redmine. Поясню на примере. Допустим, адрес нашего сайта - prefix следует удалить из файла конфигурации полностью!
Настройка nginx.
В каталоге /etc/nginx/ следует создать файл proxy_params.conf. На моих серверах он выглядит примерно так:
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 20m;
client_body_buffer_size 1m;
proxy_buffering off;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_connect_timeout 180;
proxy_buffer_size 4k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 1m;
add_header X-Frame-Options "SAMEORIGIN";
При необходимости измените настройки, исходя из параметров вашего сервера. Указанные в примере данные хорошо себя показали на не очень мощной машине с 2 GB RAM.
В каталоге /etc/nginx/conf.d/ создадим файл redmine.conf со следующим содержимым:
upstream redmine {
server unix:/var/run/redmine/redmine.0.sock;
}
server {
listen 80;
server_name sharkon.ru;
access_log off;
error_log /var/log/redmine/nginx_error.log;
include /etc/nginx/proxy_params.conf;
proxy_redirect off;
location / {
root /var/www/sharkon.ru;
}
location /redmine {
root /usr/share/redmine/public;
error_page 404 404.html;
error_page 500 502 503 504 500.html;
try_files $uri/index.html $uri.html $uri @redmine_server;
}
location @redmine_server {
proxy_pass http://redmine;
}
}
Здесь указано, что следует использовать для соединения с Redmine сокет, расположенный по пути /var/run/redmine/. Имя сокета формируется из строки, указанной ранее в параметрах thin плюс порядковый номер созданного сокета, начиная с нуля. Далее идёт указание имени нашего сервера и пути, по которому расположен Redmine. Все запросы к нему автоматически будут переадресовываться к созданному ранее сокету.
Миграции
Т.к. мы настраивали доступ к БД вручную, создание её структуры мы будем производить вручную. Это не сложно:
cd /usr/share/redmine
rake db:migrate RAILS_ENV=production
Права на сокет
Так как сокет для redmine будет создаваться пользователем www-data, следует сделать так, чтобы после перезагрузки системы Redmine мог создать его заново. Для этого мы сменим владельца папки с сокетами и pid-файлом.
cd /var/run
mkdir redmine
chown www-data:www-data redmine/
Кодировка CSV-файлов
По-умолчанию Redmine генерирует все отчёты в кодировке UTF-8. Пакет Microsoft Office использует кодировку Win1251, поэтому CVS-отчёт, открытый с помощью Excel, будет показывать кракозябры. Следует всего лишь в одном месте изменить настройки:
cd /usr/share/redmine/config/locale
nano ru.yml
Здесь следует найти строку:
general_csv_encoding: UTF-8
и заменить её на
general_csv_encoding: CP1251
При необходимости здесь же можно изменить и другие параметры локализации Redmine, например, перевод некоторых слов и кодировку файлов pdf.
Запуск
Все подготовительные операции выполнены, можно запустить сам Redmine и перезапустить nginx.
service thin start
service nginx restart
Redmine будет доступен по адресу
Nginx + PHP-FPM в Debian 7
Введение
В статье рассматривается настройка сервера Debian 7 для размещения проектов PHP в связке с Nginx и PHP-FPM.Долгое время мне вполне хватало возможностей Apache для разработки моих проектов на PHP. Были некоторые трудности с .htaccess и перенаправлением всех запросов на Front Controller, однако, чуть позже я понял, что Apache уже не может полностью удовлетворить моей тяги к максимальной производительности и начал искать другие пути. Почитав, я выяснил, что доля интернет-серверов под управлением Apache неуклонно снижается на протяжении уже нескольких лет, на замену ему приходят другие, которые дают бОльшую произодительность с меньшей затратой машинных ресурсов. Среди множества решений я выбрал PHP-FPM. Судя по тестам производительности, произведённым многими энтузиастами, именно он в связке с Nginx является наиболее перспективным способом размещения сайтов на PHP.
Цели
- Увязка PHP-FPM с nginx
- Конфигурирование параметров сайта для его корректной работы через Front Controller
Установка необходимого ПО
Добавим в список репозитории nginx, предварительно создав файл nginx.list в каталоге /etc/apt/sources.list.d/:
cd /etc/apt/sources.list.d/
touch nginx.list
/etc/apt/sources.list.d/nginx.list
deb http://nginx.org/packages/debian/ wheezy nginx
deb-src http://nginx.org/packages/debian/ wheezy nginx
Скачиваем ключ репозитория:
wget http://nginx.org/keys/nginx_signing.key
Установка ключей в deb-системах делается так:
apt-key add nginx_signing.key
Теперь можно выполнить установку всех необходимых программ:
apt-get update && apt-get install php5 php5-fpm nginx -y
Кратко по списку:
- php5 и php5-fpm - интерпретатор и FastCGI-сервер для него
- nginx - проксирующий сервер, будет нашим Front-End, т.е. сервером, принимающим запросы пользователя. Не путать с Front Controller, это совершенно разные вещи!
Настройка PHP и PHP-FPM
При установке PHP-FPM создаёт внутри каталога /etc/php5 подкаталог fpm. Внутри этого каталога находится несколько нужных нам файлов и подкаталогов. Первым делом вносим изменения в файл /etc/php5/fpm/php.ini
cd /etc/php5/fpm
nano php.ini
Здесь множество настроек, которые влияют на поведение PHP. В качестве символа комментария следует использовать точку с запятой. Самыми полезными я считаю следующие настройки:
- short_open_tag = Off - использование коротких тегов считать ошибкой. Официальная документация по PHP рекомендует не использовать короткие теги.
- asp_tags = Off - мы тут всё-таки на PHP пишем, а не на ASP.NET
- max_execution_time = 60 - для некоторых CMS, например, Drupal, стандартных 30 секунд часто не хватает для выполнения некоторых скриптов, например, обновления
- error_reporting = E_ALL - разработчику нужно видеть все ошибки. Если сервер боевой, нужно выставить в значение E_ALL & ~E_DEPRECATED & ~E_STRICT
- display_errors = On - для разработки, для боевых условий - Off
- display_startup_errors = On - аналогично
- post_max_size = 16M - можно и больше, если через POST будут передаваться достаточно большие объёмы данных
- default_charset = "UTF-8" - обязательно, если хочется избавиться от большинства проблем с кодировкой. Осторожно! Настройка влияет на весь сервер. Также кодировку можно задать в самом скрипте!
- cgi.fix_pathinfo=1 - пригодится, если приложение работает через Front Controller
- upload_max_filesize = 32M - можно и больше, если на сервер будут загружаться большие файлы
- default_socket_timeout = 60 - в нашем случае связь с Nginx будет именно через сокет. Не стоит выставлять слишком большие значения, это приведёт к падению производительности.
Остальные настройки в этом файле можете делать по своему усмотрению.
Теперь нужно подредактировать файл www.conf в каталоге pool.d/www.conf
nano pool.d/www.conf
Следует изменить user и group на те, от имени которых будут выполняться скрипты. Не следует выполнять их от имени root, это дыра в безопасности. Я рекомендую указывать здесь владельца каталога /var/www
user = www-data
group = www-data
Не менее важная настройка:
listen = /var/run/php5-fpm.sock
Именно через этот сокет будет производиться обмен данными с Nginx. Остальные настройки я рекомендую оставить по умолчанию. Их тонкая настройка заслуживает отдельной подробной статьи.
После сохранения изменений следует перезапустить php-fpm:
service php5-fpm restart
Настройка Nginx
Перейдём в каталог настроек nginx:
cd /etc/nginx/
Здесь нам нужны 2 файла:
- nginx.conf - основной файл конфигурации сервера
- fastcgi_params - настройки Nginx для работы с FastCGI-серверами, например, PHP-FPM
Я привёл содержимое этих файлов к следующему виду:
nginx.confuser nginx;
worker_processes 2; # По числу ядер/процессоров, либо эмпирическим путём
worker_priority -5; # Отрицательные числа задают более высокий приоритет
worker_rlimit_nofile 2048; # Можно открыть сразу 2048 подключений без изменения параметров ядра
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 60; #Поддерживать подключение 1 минуту
client_max_body_size 20m; #Разрешить загрузку файлов до 20 МБ
server_tokens off;
#Сжатие передаваемых данных
gzip on;
gzip_disable "msie6";
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml+rss text/javascript;
include /etc/nginx/conf.d/*.conf;
}
В конец файла fastcgi_params нужно добавить всего одну строчку, вот эту:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Теперь в каталоге /etc/nginx/conf.d/ создадим файл site.conf
nano /etc/nginx/conf.d/site.conf
index index.php;
server {
server_name www.site.ru;
rewrite ^ $scheme://site.ru$request_uri? permanent;
}
server {
server_name site.ru;
access_log /var/www/site.ru/log/access.log;
error_log /var/www/site.ru/log/error.log;
root /var/www/site.ru;
location / {
try_files $uri $uri/ /index.php?$request_uri;
index index.php;
}
location ^~ /protected/ {
deny all;
}
location ~ \.php$ {
try_files $uri = 404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
Разберём по частям этот файл:
index index.php;
Считать страницей по-умолчанию index.php
server {
server_name www.site.ru;
rewrite ^ $scheme://site.ru$request_uri? permanent;
}
Все запросы на http://www.site.ru автоматически переадресовывать к http://site.ru/
server_name site.ru;
access_log /var/www/site.ru/log/access.log;
error_log /var/www/site.ru/log/error.log;
root /var/www/site.ru;
Собственно наш сервер, с указанием его имени, логов и указанием корневого каталога
location / {
try_files $uri $uri/ /index.php?$request_uri;
index index.php;
}
Тут указано, что все запросы вида http://site.ru/login/auth следует переадресовывать к http://site.ru/index.php - как раз то, что нужно для Front Controller'а
location ^~ /protected/ {
deny all;
}
Запрещаем любые обращения к папке protected нашего сайта. Там лежат исходные коды, к которым будет обращаться только index.php, веб-сервер их отдавать не должен.
location ~ \.php$ {
try_files $uri = 404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
Выдавать ошибку 404, если запрошенный php-файл не найден. В остальном - просто переадресовать запрос на наш PHP-FPM-сервер. Также в этих строках выполняется подключение файла настроек /etc/nginx/fastcgi_params.
После выполнения всех операций следует перезапустить сервис Nginx
service nginx restart
Если исходные файлы сайта размещены в каталоге /var/www/site.ru/, а также этот каталог содержит подкаталог log, владельцем которого является www-data, то при обращении к сайту мы увидим главную страницу.

