Pull to refresh

Установка Asp.Net на Linux (nginx+mono+xsp)

Nginx *
В этой статье я покажу, как настроить простую связку nginx + Asp.Net. Под простой надо понимать, что какие-то специфические особенности проектов, разграничение прав пользователей, высокие нагрузки и т.п. нужно настраивать отдельно (особенно это касается Asp.Net). Статья написана по просьбе хабраюзера mace.

В свое время озадачившись проблемой хостинга маленьких Asp.Net-проектов я осознал одну простую вещь: покупать лицензию на Windows Server, а потом и арендовывать достаточно мощный выделенный/виртуальный сервер для каких-то домашних поделок/экспериментов — крайне неразумно. Решение как-то сразу всплыло в моей лысой голове: есть же Mono! Непродолжительный поиск по mono-project.com вывел на FAQ об Asp.Net. Фактически, документация показала мне три возможных варианта:

You need the Mono runtime and use one of Apache with mod_mono, a CGI or FastCGI-aware web server with Mono's FastCGI support or the xsp standalone server (all available from our downloads page).

Быстрый анализ интернета, для выбора одного из этих способов, привел меня к статье Максима Крентовского (mkrentovskiy), это достаточно забавно, т.к. спросить у Максима в аське я почему-то не догадался.

Выводы Максима показались мне достаточно убедительными. Я не стал проводить какие-то дополнительные тесты или искать другие источники, для моей задачи ответ был уже очевиден: nginx + xsp. Учтите, в wiki Mono сказано, что xsp надо использовать для отладки и разработки!

Установка nginx

Итак, мы имеем свежеустановленный Debian Squeeze x64 Minimal. Самый простой вариант установки последних версий nginx — установка из репозиториев dotdeb.org. Кстати, очень хороший репозиторий: в нем, помимо nginx, всегда последние версии php, mysql (percona) и redis. Чуть сложнее установить из исходников — об этом чуть ниже.

Добавим в sources.list новый репозиторий, пропишем GnuPG-ключ и обновим источники:
root@falco:~# echo "deb http://packages.dotdeb.org stable all" >> /etc/apt/sources.list
root@falco:~# wget -q http://www.dotdeb.org/dotdeb.gpg -O- | apt-key add -
root@falco:~# apt-get update

Если все сделано правильно, то на команду apt-cache policy nginx мы увидим следующее:
root@falco:~# apt-cache policy nginx
nginx:
  Установлен: (отсутствует)
  Кандидат:   1.0.2-1~dotdeb.1
  Таблица версий:
     1.0.2-1~dotdeb.1 0
        500 http://packages.dotdeb.org/ stable/all amd64 Packages
     0.7.67-3 0
        500 http://mirror.yandex.ru/debian/ squeeze/main amd64 Packages

Существует три разных пакета, собранных с разными наборами модулей: nginx-lite, nginx-full (пакет nginx как раз его алиас) и nginx-extras. Какой устанавливать — решать вам, нам бы хватило и lite версии (Proxy есть и ладно), но на момент написания статьи я уже установил full, поэтому будем устанавливать его:
root@falco:~# apt-get install nginx

Вот и все шаги для установки из пакетов.

Если вы устанавливаете nginx из исходников, то ./configure надо запускать с такими параметрами:
./configure --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module

Это будет практически соответствовать пакету nginx-full, за исключением отсутствия сторонних модулей Upstream Fair Queue и Echo.

Установка Mono

Для Mono таких удобств с репозиториями нет, придется сразу компилировать последние исходники.

upd. Как справедливо заметил Net_Rat, я немного слукавил: можно подключить экспериментальный репозиторий и через pining настроить установку mono и xsp оттуда.

Качаем последние исходники mono и xsp (на момент написания 2.10.2):
root@falco:~# wget "http://ftp.novell.com/pub/mono/sources/mono/mono-2.10.2.tar.bz2"
root@falco:~# wget "http://ftp.novell.com/pub/mono/sources/xsp/xsp-2.10.2.tar.bz2"

Теперь распакуем архивы:
root@falco:~# tar -xvf mono-2.10.2.tar.bz2
root@falco:~# tar -xvf xsp-2.10.2.tar.bz2

Если tar ругнется на отсутствие bzip2 (в minimal точно ругнется), его нужно поставить:
root@falco:~# apt-get install bzip2

Для компиляции mono и xsp нам понадобится следующее:
root@falco:~# apt-get install build-essential gawk bison gettext libgdiplus pkg-config libglib2.0-0 libglib2.0-dev

Приступим к конфигурированию и компиляции (процесс непосредственно компиляции может занять продолжительное время, до 20-30 минут):
root@falco:~/mono-2.10.2# ./configure --prefix=/usr --sysconfdir=/etc/mono
root@falco:~/mono-2.10.2# make && make install

Если установка прошла успешно, то запуск команды mono --version покажет нам заветное и долгожданное:
root@falco:~/mono-2.10.2# mono --version
Mono JIT compiler version 2.10.2 (tarball Сбт Июн 11 15:54:39 MSD 2011)
Copyright (C) 2002-2011 Novell, Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        LLVM:          supported, not enabled.
        GC:            Included Boehm (with typed GC and Parallel Mark)

Теперь установим xsp:
root@falco:~/xsp-2.10.2# ./configure --prefix=/usr --sysconfdir=/etc/xsp
root@falco:~/xsp-2.10.2# make && make install

Весь xsp написан на C#, компиляция должна пройти очень быстро. Проверим, что оно нам выдаст:
root@falco:~# xsp4 --version
xsp4.exe 2.10.2.0
Copyright (C) 2002-2011 Novell, Inc.
Minimalistic web server for testing System.Web

Похоже, все схватилось. Пора переходить к настройке.

Настройка Xsp

Создадим директорию нашей будущей странички Hello World:
root@falco:~# mkdir -p /var/www/asptest

Сразу создадим классический «Hello World» для пробы:
root@falco:~# cd /var/www/asptest
root@falco:/var/www/asptest# nano Default.aspx

В файле напишем следующие строки:
<%@ Page language="C#" %>
<html>
	<head>
		<title>Hello C#</title>
	</head>
	<body>
		<p><% Response.Write("Hello World");%></p>
	</body>
</html>

Поскольку xsp изначально задумывался как тестовый сервер, скриптов запуска демона там нет. Будем исправлять такую ситуацию. Создадим файл /etc/default/xsp, и запишем в него переменные по-умолчанию:
user=www-data
group=www-data

port=8080
address=0.0.0.0

Создадим файл /etc/init.d/xsp, дадим ему права на выполнение (chmod +x /etc/init.d/xsp) и в него напишем:
#!/bin/sh
### BEGIN INIT INFO
# Provides:          xsp
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Asp.Net testing server startup script.
# Description:       Asp.Net testing server startup script.
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=xsp
NAME=xsp
DAEMON=/usr/bin/xsp4
DEFAULT=/etc/default/$NAME
DAEMON_ARGS="--nonstop --root /var/www/asptest"
#DAEMON_ARGS="--nonstop --root /usr/lib/xsp/test"
MONO_SHARED_DIR=/var/run/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

[ -x "$DAEMON" ] || exit 0
[ -f "$DEFAULT" ] && . $DEFAULT

. /lib/lsb/init-functions

if [ ! -e $MONO_SHARED_DIR ]; then
        mkdir $MONO_SHARED_DIR
        chown $user:$group $MONO_SHARED_DIR
fi

chk_start() {
        if [ -f "$PIDFILE" ]; then
                xpid=`head -1 "$PIDFILE"`
                xps=`ps -p $xpid | wc -l`
                if [ "$xps" != "1" ]; then
                        log_action_msg "Xsp is running"
                        return 1
                fi
        fi
        return 0
}

do_start()
{
        export MONO_SHARED_DIR
        start-stop-daemon --start --background --make-pidfile \
                --quiet --pidfile /var/run/$NAME.pid \
                --user $user --group $group --chuid $user \
                --exec $DAEMON -- \
                --port $port --address $address \
                $DAEMON_ARGS
}

do_stop()
{
        if [ -e "$PIDFILE" ] ; then
                kill -9 `head -1 "$PIDFILE"` 1>/dev/null 2>&1
                rm -f "$PIDFILE"
        fi
}

case "$1" in
  start)
        if chk_start ; then
                log_daemon_msg "Starting $DESC" "$NAME"
                do_start
                log_end_msg $?
        fi
        ;;
  stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        log_end_msg $?
        ;;
  status)
       ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        do_start
        log_end_msg $?
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

:

В скрипте запуска так же имеется закомментированная строка для папки с тестами из дистрибутива xsp, для более полноценной картины.

Добавим его в автозапуск с дефолтными уровнями запуска (поправить по надобности) и запустим наш новый демон:
root@falco:~# update-rc.d xsp defaults
root@falco:~# /etc/init.d/xsp start

По-умолчанию, сервер слушает на всех интерфейсах, проверить легко:
root@falco:~# netstat -nlp | grep 8080
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      20839/mono

Если перейти по http://serveraddr:8080/ можно увидеть долгожданное «Hello World»:


А если вы переключите на тестовую страницу xsp, то:


Настройка nginx

Суть настройки nginx в проксировании обращений только для asp-файлов. Остальные статические файлы должен раздавать nginx. Не мудрствуя особо сильно, возьмем конфигурацию, которую предложил Максим Крентовский в своей статье и чуть-чуть изменим под наш случай:
server {
        listen 80;
        server_name  serveraddr.ru;
        location / {
                root /var/www/asptest
                #root /usr/lib/xsp/test;
                index index.html index.htm index.aspx default.aspx Default.aspx;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   html;
        }
        location ~ \.(aspx|asmx|ashx|axd|asax|ascx|soap|rem|axd|cs|config|dll)$ {
                root /var/www/asptest
                #root /usr/lib/xsp/test;
                proxy_pass   http://127.0.0.1:8080;
        }
}

Как управлять виртуальными хостами nginx лучше всего знает гугл.

Открыв http://serveraddr.ru/ получаем долгожданное «Hello World»:


Или, для тестовых настроек:


Вот и все. Повторюсь, что в wiki Mono ясно указано, что xsp лучше использовать для тестов!

Это мой первый пост на хабре, прошу не кидать в меня кирпичи и другие булыжники… Буду очень рад любой критике, как по содержанию статьи, так и по орфографии с пунктуацией. И да, я мог ошибиться с выбором блога. Если так — скажите куда лучше поместить.

P.S. Сам я, хоть и люблю .Net/C#, с Asp.Net совершенно не знаком, даже Hello World из статьи писал с помощью Гугла. Так что задавать вопросы по Asp.Net и Asp.Net MVC мне бесполезно. :-)
Tags:
Hubs:
Total votes 88: ↑74 and ↓14 +60
Views 38K
Comments Comments 36