понедельник, 2 апреля 2018 г.

Восстановление БД с изменением имени в MSSQL

Проблема
Необходимо скопировать и восстановить одну из БД на том же инстансе (экземпляре) SQL сервер.

У MSSQL  все базы данных имеют логическое имя и обычно состоят из 2 файлов (файла данных и файла лога), имеющие следующие имена:

logicalName_Data.mdf
и
logicalName_Log.ldf

Иногда возникают ситуации когда необходимо "скопировать" БД на этот же инстанс SQL-сервера, но с новым логическим именем т.к., например, копируемая БД используется одним или несколькими приложениями.

Решение
Я не нашел как решить эту проблему в SQL Management Studio без операций по переименовыванию исходной БД (одно из условий: БД используется одним из приложений, поэтому ее трогать нельзя). Решение довольно простое, но для этого еужно написать TSQL-инструкцию.

1. Вывод списка файлов бэкапа:
RESTORE FILELISTSTONLY FROM DISK = 'E:\backups\mydb.bak'

в моем случае я получил mydb] для Data-файла и mydb]_log для файла логов

2. теперь скопируем имена файлов из выведенной таблицы в слебующую инструкцию:

RESTORE DATABASE myNewDb FROM DISK = 'E:\backups\mydb.bak'
WITH
RECOVERY,
MOVE 'mydb]' TO 'E:\db\data\myNewDb.mdf',
MOVE 'mydb]_log' TO 'E:\db\logs\myNewDb.ldf'; 

База восстановлена с новым именем myNewDb.

вторник, 2 января 2018 г.

Развертывание Asp Net Core на IIS

Как развертывается Asp Net Core

Asp Net Core - это как Проктор энд Гэмбл т.е. два в одном флаконе: фрэймворк и Web-сервер, а само веб приложение  имеет вид консольного приложения, развертываемого через IWebHost с предварительной настройкой сервисов, миддлваре и т.п. Все относительно просто в случаях, когда разработка идет на машине с установленной Visual Studio. Для запуска веб приложений в Asp Net Core используется веб-сервер Kestrel. И, казалось, бы нет никаких сложностей для запуска веб-приложения на IIS. Но, столкнувшись с такой задачей я набил кучу шишек, о чем и хочу рассказать в этом посте.

Создание Net Core пула и подключение модуля AspNetCore

Как известно в IIS имеются пулы, которые, используются во-первых, для изоляции одних приложений от других, а, во-вторых, для простоты настройки однотипных приложений. И если запустить настройку пула приложения на IIS, то можно увидеть, что Net Core в нем напрочь отсутствует (предварительно я установил Net Core Sdk), всего 3 варианта таргет фрэймворка для пула: 2.0, 4.0 и неуправляемый код. Для Asp Net Core нужно выбрать последний. 

Но и это еще не все: выше я писал, что Asp Net Core веб-приложение развертывается на веб-сервере Kestrel, а как же тогда подключить IIS, дело в том, что IIS подключается как прокси: все запросы, пришедшие на HTTP порт приложения, развернутого на IIS, маршрутизируются через модуль AspNetCore в Kestrel, обрабатываются приложением, а ответ направляется в IIS. За это взаимодействие отвечает AspNetCore модуль, который необходимо установить в IIS отдельно от Net Core Sdk!!!! (https://docs.microsoft.com/ru-ru/aspnet/core/fundamentals/servers/aspnet-core-module). После инсталляции в списке модулей должна быть эта строка (предварительно (сначала) необходимо установить VS2015 C++ Redistributable Package):
Кроме всего этого в Web.config необходимо указать использование этого модуля и путь к целевой сборке (приложению), например, мое приложение - E3App.Web.dll и Web.Config имеет следующий вид:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore
        processPath="dotnet"
        arguments=".\E3App.Web.dll"
        stdoutLogEnabled="true"
        stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>

Этот файл, как и многое другое, генерируется в процессе публикации проекта (Publish), однако, я не думал, что он играет роль, т.к. он в явном виде отсутствует в проекте. Но он очень важный! Особенно атрибут stdoutLogEnabled, по умолчанию этот атрибут имеет значение false, что для разработчика означает следующее: любое исключение произошедшее при запуске приложение будет "проглочено", а в качестве результата мы увидим на странице что-то вроде: "Оопс, а что-то сломалось". Включаем и идем дальше.

Старая добрая БД и EF Core

Следующим приколом на пути к запуску приложения стала сама БД: я поставил Sql Server 2012, предполагая, что EF нет дела до версии SQL сервера, но не тут-то было (хотя мне казалось, что ву меня был рабочий проект под 12 версию сервера). Текст исключения в стандартном выводе мне ничего не говорил о том, почему у меня ломается приложение при старте. Однако, подозрительным было то, что при отладке приложение стартовало без каких-либо проблем, а на IIS - ломалось. Тогда я решил заменить 12 SQL Server на SQL Server 2016 и вуаля, текст ошибки стал другим. Теперь приложение жаловалось на то, что нет прав на создании новой БД при подключении к таблице master (тут все тривиально, нужна роль sysadmin для пользователя под которым выполняется подключение). Хотелось бы сделать ремарку о том, что EF работает с БД по парадигме Code First (сам создает скрипт для создания БД, всех таблиц и связей между ними). Тут тоже пришлось помучиться, т.к. можно сделать строку подключения с полным указаниям логина и пароля (в appsettings.json):

  "ConnectionStrings": {
    "Storage": "Server=DEV-HOST\\SQLEXPRESS;Database=e3app;
    User ID=developer;Password=123;MultipleActiveResultSets=true"
  }


 Но это не всегда удобно использовать заранее созданную учетную запись, иногда необходимо использовать Windows-аутентификацию, казалось бы просто выдал права (роль sysadmin) своей Windows учетной записи:

"ConnectionStrings": {
    "Storage": "Server=DEV-HOST\\SQLEXPRESS;Database=e3app;
    Integrated Security=SSPI;MultipleActiveResultSets=true"
 }


 но нет в БД, оказывается, EF лезет через другую учетку. Экспериментальным способом включая данную роль у логинов по очереди, определил, что это  учетная запись BULTIN\Users (а если посмотреть, кто создал БД - IIS APPPOOL/AspNetCore).



Заключение

Казалось бы тривиальная задача, но она отняла у меня кучу времени, я убил, наверное, пару дней чистого времени пытаясь понять, что происходит и почему все работает не так, как нужно. Надеюсь, что этот пост поможет тем, кто столкнулся с такой же проблемой: деплоя на IIS Asp Net Core веб приложения.



воскресенье, 12 ноября 2017 г.

Анонимный доступ в Samba

Как настроить полностью анонимный доступ к Samba сервису

Данное очень короткое сообщение, скорее напоминание самому себе как это делается,  т.к. на одном из моих одноплатников, а именно на том, на котором крутился мой файлообменник, умерла карта памяти, чтобы не вспоминать по 10 раз снова как это делается (а внутри домашней сети мне нет смысла делать доступ по паролю) я здесь выложу файл конфигурации Samba для полностью анонимного доступа:

[global]
workgroup = FAMILY
server string = Cubie Samba Server
dos charset = cp1251
unix charset = utf8
dns proxy = no
security = user
browseable = yes
log file = /media/other/samba/smbd.log
syslog = 0
map to guest = Bad Password
guest account = nobody
browseable = yes

[shared]
comment = Guest access share
path = /media/samba/shared
browseable = yes
read only = no
guest ok = yes
writable = yes
public = yes
available = yes

Комментировать тут особенно нечего, поэтому если кому-то понадобится, пользуйтесь на здоровье.

четверг, 9 ноября 2017 г.

Десериализация в ASP NET Core 2.0

Будни кросс-платформенного Web от Microsoft

ASP NET Core базируется на платформе NET Core, которая, в свою очередь является кросс-платформенной, на данный момент доступна версия 2.0.х (у меня NET Core работает, что под Windows 7, что под Linux Mint 18).  Сам ASP NET Core включает в себя Entity Framework, Json Converter (от Newtonsoft), IoC и т.п. Сегодня пойдет речь о работе с Json, точнее о том, что я в итоге получил.

Приколы с POST и PUT и десериализацией из Json

Предположим у нас есть два проекта в солюшене, пусть они называются ClickPlatform.Dto и ClickPlatform.Mvc. В первом у нас объявлены классы Dto - объектов, а вот втором - Web API с набором контроллеров с методами (Get, Post, Put и Delete для обработки одноименных HTTP-методов и действий).

У нас есть следующий класс Dto:

    public class Listing
    {
          public Listing() { }

          public Listing(Guid id, string name, AdShortInfo[] linkedAd = null, string status = null,                                              TotalStatistics stats = null)
          {
               Id = id;
               Name = name;
               LinkedAd = linkedAd;
               Status = status;
               Stats = stats;
          }

          public Guid Id { get; set; }
          public string Name { get; set; }
          public AdShortInfo[] LinkedAd { get; set; }
          public string Status { get; set; }
          public TotalStatistics Stats { get; set; }
    }

Понятно, что для получения объекта и коллекции объектов используем Get-методы, с сериализацией тут все ок, все хорошо работает. и мы получаем либо коллекцию объектов, либо отдельный объект по id. Чудеса начинаются при использовании методов Post и Put внутри следующего контроллера

    [Produces("application/json")]
    [Route("api/[controller]")]
    public class ListingController : Controller
    {
        .// ...
       
        [HttpPost]
        public void Post([FromBody] Dto.Internal.Listing listing)
        {
    _listingManager.Create(listing);
        }

        [HttpPut("{id}")]
        public void Put([FromRoute]Guid id, [FromBody]Dto.Internal.Listing listing)
        {
            _listingManager.Update(id, listing);
        }
       
        // ...
   }

   Пробуем дернуть Post при этом устанавливаем content-type=application/json и charset=utf-8. и передаем следующий json: {"id":"","status":"active","name":"Evil_One","linkedAd":[], "stats":""}


Точка останова показывает нам, что наш объект - null.


Если мы поставим object, то получим следующее:

[HttpPost]
public void Post([FromBody] /*Dto.Internal.Listing*/ object listing)
{
     //_listingManager.Create(listing);
}


Теперь объект в теле определился, получается, что Json не может десериализовать объект в Dto.Internal.Listing. Почему же так происходит?  Все дело оказывается в том, что если для value type значение в Json не задано, то считается, что там null, а null нельзя использовать для value-типов, поэтому приходится везде ставить Nullable<T>. В вышеприведенном коде поменяет  свойство Guid Id {get; set;} на Guid? Id {get; set;}. И теперь смело можем передавать запрос со значением ""  в качестве Guid

При этом сам Newtonsoft.Json не соизволил проинформировать о том, что он не может десериализовать тип. Что ж вот такая она десериализация объектов в Asp NET.

Послесловие (послевкусие)
Попробовал я ASP NET Core и не могу сказать, что это супер платформа, не могу сказать, что это именно то, что нужно для разработки. В ней вроде как бы все есть, но что-то в ней не так. Многие вещи кажутся странными: как например молчаливая обработка ошибок, подтягивание Nuget пакетов для самых очевидных вещей вроде System.Data и многое другое. Если сюда добавить работу только на VS17 (на мой взгляд, худшая студия начиная с 2003, даже 2010 была лучше).





понедельник, 4 сентября 2017 г.

Как начать работать с HDL и ПЛИС (FPGA)

Предисловие

Планирую написать ряд статей, про внутреннее устройство ПЛИС и их программирование. В данном сообщении я планирую дать направление читателю, что нужно прочитать для того, чтобы начать разрабатывать для ПЛИС.

Современные тенденции

К сожалению, а может быть и к счастью (в зависимости как на это посмотреть) разработка современной электроники, особенно цифровой, но не только сводится к описанию цифровых функций и автоматов сводится к описанию их на основе одного из HDL (Hardware Description Language) -языков описания аппаратуры. На данный момент, существуют следующие языки описания аппаратуры: AHDL, VHDL, Verilog и System Verilog. Сами ПЛИС (CPLD, FPGA) представляют собой квадратные матрицы ячеек (состоящих из сотен - тысяч, в зависимости  от ресурсов ПЛИС, логических элементов), к этим ячейкам подходят магистрали источников синхросигналов (клоков) и линий питания (+5 или +3,3 В) и земли.  К слову говоря, современные ПЛИС (7 серия от Xilinx, 5 поколение Cyclone и т.п.) - это SoC в которых кроме, самой ПЛИС присутствует процессорное ядро и аппаратная поддержка различных интерфейсов таких, как : USB, Ethernet, CAN, SPI, I2C, RS232 и др.

Три кита разработки цифровых устройств с использованием ПЛИС (FPGA)

 1. Основа всего это алгебра логики (булева алгебра) и способы построения простых цифровых схем и автоматов с использованием алгебры логики.

2. Схемотехника входных и выходных каскадов логических элементов (для понимания, что такое высокоимпедансное Z-состояние, нагрузочные характеристики элементов, схемы с открытым коллектором).

3. И, конечно, 3 этап это способы построения простых цифровых схем с использованием языков описания аппаратуры.

Алгебра логики

Основными в алгебре логики являются следующие вещи:

1) Принцип двойственности
2) Теорема Де-Моргана 
 
 Эти два принципа можно посмотреть, например, здесь: https://studme.org/2002061028280/tovarovedenie/algebra_logiki . Позже сам напишу про алгебру логики.

Так же следует упомянуть про способы представления (алгебраическое, табличное и в виде карт/диаграм Карно и Вена) и минимизации логических функций через карты Карно или другие методы, например, метод Мак-Класки (https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%9A%D1%83%D0%B0%D0%B9%D0%BD%D0%B0_%E2%80%94_%D0%9C%D0%B0%D0%BA-%D0%9A%D0%BB%D0%B0%D1%81%D0%BA%D0%B8).

Одна неплохая презентация про алгебру логики: https://drive.google.com/file/d/0B9GLCHSwsJn8cURyT3BOUEVxdVE/view?usp=sharing

После понимания математических основ цифровой электроники нужно двигаться к способам реализации простых цифровых схем клмбинационной логики (логики не зависящей от состояния схемы):

- мультиплексоры
- дешифраторы
- преобразователи кода
- и другие схемы.

Вот, например, https://drive.google.com/open?id=0B9GLCHSwsJn8NmxtTVNUOVZZbWs

 Следующий шаг - изучение последовательностных схем (схемы зависящие от состояния и сигналов на входе схемы).  Такими схемами являются:

-триггеры
-счетчики
-регистры
-генераторы
и др.

Например, https://distant.msu.ru/pluginfile.php/38192/mod_resource/content/1/%D0%9B%D0%B5%D0%BA%D1%86%D0%B8%D1%8F%204.pdf

или

https://drive.google.com/open?id=0B9GLCHSwsJn8YkJZeGtVZzZ4LTQ

а также ознакомиться с описанием цифровых автоматов (которых, 2 основных вида: Мили и Мура (https://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D0%9C%D1%83%D1%80%D0%B0_%D0%B8_%D0%9C%D0%B8%D0%BB%D0%B8)

Схемотехника логических элементов

Данный раздел в большей степени относится к разаботке цифровых устройств с использованием дискретных микросхем, однако, в ряде моментов при проектировании с использованием ПЛИС эти знания также оказываются необходимыми

Прежде всего схемотехника зависит от типа логики: ТТЛ (ТТЛШ), КМОП и ЭСЛ: http://www.inp.nsk.su/students/radio/lectures/Pulse/07.pdf

Параметры логических элементов:
 http://myrepititor.ru/electronics/82-Osnovnye_xarakteristiki_i_parametry_logicheskix_eleme.html

http://audioakustika.ru/node/1555

Языки HDL, способы проектирования
У меня довольно большаыя подборка книг по ПЛИС: https://drive.google.com/open?id=0B9GLCHSwsJn8Z0Y3U24ybmxjVjA

Если использовать Verilog, то стоить начать с Verilog и VerilogTutorial, если VHDL - то "Языки Verilog и VHDL", кроме того среди этого архива есть документ с "Золотыми ссылками по HDL".


Что будет в продолжении?

В будущем планирую пройтись по каждому из этих пунктов и написать цикл статей с примерами дизайна цифровых схем (на github).

суббота, 29 июля 2017 г.

C++ symbol lookup error при запуске приложения

Суть проблемы
 
Недавно, занимаясь одним из своих С++ проектов обнаружил следующее занимательное поведение программы, использующих динамическую библиотеку. На самом деле, неважно какая библиотека вызвала данную проблему, я уверен, что это не имеет никакого значения. Но в моем случае данная проблема возникла с библиотекой libuhd. Я собрал для себя специальную версию ibuhd, успешно скомпилировал и слинковал приложение с либой и бац! при запуске:
linux; GNU C++ version 4.8.5; Boost_105800; UHD_003.010.001.001-0-unknown

/home/michael/Projects/eclipse/C++/wirelessdriver/UhdRadio/Debug/UhdRadio: symbol lookup error: /home/michael/Projects/eclipse/C++/wirelessdriver/UhdRadio/Debug/UhdRadio: undefined symbol: _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs




Причина в отсутствии функции в классе библиотеки или самого класса! Собирал я это чудо cmake, и, как оказалось, в cmake также можно задавать видимость определенных классов, но предварительно я снял все ограничения, экспортировал все, что есть. Сижу недоумеваю, пью кофе и тихо матерюсь ("С++, что же ты со мной делаешь!").

Дьявол скрывается в мельчайших деталях

В первую очередь решил проверить, а есть ли в библиотеке такой символ. Для таких целей в Linux есть утилита nm. Она позволяет вывести список экспортируемых символов, но он оказывается гигантским, поэтому используем ее совместно с grep, получаем:

~/Projects/eclipse/C++/wirelessdriver/UhdRadio/uhd-release_003_010_001_001/host/build/lib> nm -D libuhd.so | grep _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs
00000000004e1ff0 T _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs


Да, что же такое! Нужные символы есть, возможно не все зависимости (библиотеки) есть в системе, но ldd показывает, что все ОК (показывает откуда (путь) подлинковываются либы). И тут меня осенило!!! Я собирал целую массу версий uhd и параллельно ставил ее из пакетов, а что же говорит ldd относительно этой либы в моей утилите???  А говорит он, что либа при запуске приложения берется не из того, же источника откуда проводилась линковка! Понятно, что для запуска либа должна быть в LD_LIBRARY_PATH, но оба пути находятся в этой переменной, а при запуске либа тянется из первого в порядке упоминания пути, а моих изменений там вовсе НЕТ. Правим и наслаждаемся спокойной работой дальше.

Заключение

С++ , GCC люблю я вас! Настолько много в вас неожиданных сюрпризов...

вторник, 11 июля 2017 г.

Бесплатный сыр SSL

SSL, паранойя браузеров и зеленый HTTPS

Собственно ситуация довольно простая: имею собственный сервер, на котором развернут Gitlab + CI в лице Hudson: пишу код, тружусь, собираю автоматически билды проектов и т.п. В один прекрасный момент захотелось, чтобы сервис был развернут на HTTPS ( это не прихоть, просто, иногда люблю зайти на свой сервер из общественных мест с общего wi-fi, а шифрования нет, что может привести к доступу ко всей информации любому, кто способен запустить wireshark или tcpdump и т.п. Примерно около двух с половиной лет назад, по довольно тривиальной схеме я создал самоподписанный сертификат по следующей схеме (из под Linux):

1) Нужно сгенерировать CSR (Certificate Signing Request), который состоит из открытого (public) и закрытого (private) ключа и доп информации. При генерации CSR нужно записать/запомнить пароль!!!!, иначе дешифровать ключ не получится и придется генерировать CSR и ключ заново.

openssl req -newkey rsa:2048 -keyout gitlab.key -out gitlab.csr

2)  Генерируем сертификат:

openssl -key gitlav.key -new -x509 -days 1536 -out gitlab.crt
 
Параметр days задает время действия сертификата - 1536. Теперь самоподписанный сертификат готов, но, современные браузеры начинают жутко параноить и разрывают соединение при наличии на сервере такого сертификата. Использование сервиса, начинает доставлять неудобства.

3) Дешифровать  ключ, который понадобится Nginx для работы по SSL:

openssl rsa -in gitlab.key -out gitlab_dec.key

Немного теории об SSL

Как работает SSL для чего нужны открытые, закрытые ключи и сертификаты? Сама безопасность обеспечивается шифрованием данных, на сервере и у клиента: при установке соединения клиент и сервер договариваются о выборе типа шифрования, сервер передает на клиент сертификат и открытый ключ, закрытый ключ остается на стороне сервера. Далее происходит генерация сеансового ключа на стороне клиента (шифрование случайной последовательности открытым ключом),  и передача их на сервер, расшифровать данные можно только с помощью закрытого ключа (т.к.) шифрование является асимметричным. Закрытый ключ находится на сервере и недоступен никому.

StartSSL и иже с ними

Жадные капиталисты за работу своих центров сертификации, хотят  деньги, поэтому, чтобы стать обладателем сертификата нужно раскошелиться на, сумму от 50 до 200$. Для хостинга своих небольших сайтов и Web-сервисов такая цена является неоправданно высокой, поэтому лучше найти варианты с бесплатным SSL. Из известных мне сервисов это StartSSL и Letsencrypt. Изначально я подсел на первый и, поэтому решил работать с ним дальше.

Полезные команды на заметку

Самым главным вопрос для меня являлось узнать/проверить а соответствует ли мой приватный ключ сертификату, чтобы это сделать наиболее просто нужно получить хэши поля modulus приватного ключа и сертификата:

openssl x509 -noout -modulus -in gitlab.crt | openssl md5
(stdin)= ca2097c19fa0af553533037e290dfb02
openssl rsa -noout -modulus -in gitlab_dec.key | openssl md5
(stdin)= 933b16d478523d8d8f3fbfceb57644e0
openssl rsa -noout -modulus -in gitlab.key | openssl md5
Enter pass phrase for gitlab.key:
(stdin)= ca2097c19fa0af553533037e290dfb02

Как видно из выхлопа консоли у одного ключа совпадает хэш с сертификатом, а у другого нет

Что делать в случае использования StartSSL

Да, я выбрал Start SSL и в 2016-м получил свой первый зеленый сертификат на целый год работы,все было хорошо. Но сертификат буквально неделю назад испарился и возобновить его нет возможности, необходимо создавать новый, что же попробуем создать новый. Сразу скажу, что сертификат выпускается на доменное имя, поэтому для того, чтобы его получить нужно где-то взять имя. Я использую dnsexit, они предоставляют бесплатные доменные имена 2го уровня в зонах типа linkpc.net и т.п.

1) Прежде всего подтверждаем, что являемся владельцами домена. Раньше в StartSSL можно было разместить страничку на сервере и пройти валидацию, теперь все только через e-mail адрес домена, который выдает whois. Я заплатил 12$ за редирект почты в dnsexit на свою почту и получил код валидации домена.

2) После валидации домена необходимо зайти в Certificate Wizard и создать csr на базе приватного ключа:
openssl req -newkey rsa:2048 -keyout um-gitlab.linkpc.net_enc.key -out um-gitlab.linkpc.net.

 3) Скачиваем сертификат из StartSSL ToolBox панели, нам нужен вот этот сертификат:

Нажимаем Retrieve и забираем весь архив. И вот тут-то начинается самое прекрасное. У Start SSL есть инструкция по установке сертификата на NGINX, только по этой инструкции сертификат поставить невозможно. Для того чтобы домучить процесс нужно запросить промежуточный сертификат, который имеет имя BR Intermediate. Из папки OtherServer взять сертификат домена и корневой сертификат (root.crt), теперь эти 3 сетификата нужно объединить в следующем порятке:
          1. Сертификат домена
          2. Промежуточный сертификат
          3. Корневой сертификат

Объединяем все это дело утилитой cat:

cat gitlab.crt BR\ Intermediate.crt root.crt > ssl-unified.crt

Ну а далее стандартная процедура накатывания сертификата на nginx: в качестве ключа берем дешифрованный приватный ключ, а в качестве сертификата ssl-unified. После установки сертификата перезагружаем nginx и теперь все готово к работе.

Проверить правильно ли сгенерировались и объединились сертификаты можно с помощью данного онлайн ресурса: https://www.sslshopper.com/ssl-checker.html Если цепочка является полной, то все ок.

И здоровенная ложка дегтя!!!!

На текущий момент у StartSSL проблемы с Chrome > 57 и Firefox, эти браузеры считают сертификаты не валидными. Поэтому я сижу, грущу и использую Konqueror. В службе поддержки мне сказали, что, вероятно, через 1-2 месяца они решат проблему с этими браузерами. Ресурсы для отслеживания этой темы:
https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/
https://bugzilla.mozilla.org/show_bug.cgi?id=1311832

Насколько сыр оказался бесплатным?

Если не считать 12 баксов на редирект электронной почты (возможно, я смог бы поднять mail-сервер, но не факт, что он стал бы работать в этом домене с нужным адресом эл. почты, поэтому я не стал тратить время на решение этого вопроса) и рабочего дня времени убитого на то, чтобы создать и установить сертификат правильно, то все остальное оказалось бесплатным, на выходе имеем сертификат валидный в течение двух лет. В целом, я считаю, это неплохим результатом и если бы цены на сертификаты были раза в два меньше, то можно было бы купить сертификат более высокого класса.

Распространение Windows-приложений (Chocolatey)

Менеджеры пакетов для ОС Windows В большинстве дистрибутивов Linux есть свои менеджеры пакетов: в Ubuntu/Mint это apt и deb, в OpenSuse э...