nginx (Русский)

nginx (произносится "э́нжин-э́кс" или "э́нжин-и́кс") — это свободный высокопроизводительный HTTP-сервер с открытым исходным кодом, а также обратный прокси и IMAP/POP3 прокси-сервер, написанный Игорем Сысоевым в 2005 году. nginx получил широкое распространение благодаря своей стабильности, богатой функциональности, простой настройке и низкому потреблению ресурсов.

Состояние перевода: На этой странице представлен перевод статьи nginx. Дата последней синхронизации: 18 июля 2022. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

Данная статья описывает установку nginx и интеграцию с PHP через #FastCGI.

Установка

Установите пакет nginx-mainline (основная ветка: новые возможности, обновления и исправления ошибок) или nginx (стабильная ветка; только исправления серьёзных ошибок).

Рекомендуется использовать основную (mainline) ветку. Основная причина для использования стабильной ветки — возможная несовместимость со сторонними модулями или непреднамеренное появление ошибок при реализации новых функций.

Примечание: Все модули nginx, доступные в официальных репозиториях, в качестве зависимости требуют пакет nginx (а не nginx-mainline). Возможно, стоит просмотреть список модулей на наличие тех, которые вам могут понадобиться, прежде чем принимать решение о выборе между nginx и nginx-mainline. Модули для nginx-mainline можно найти в пользовательском репозитории Arch.

Если для обеспечения дополнительной безопасности вы хотите установить nginx в chroot-окружении, смотрите раздел #Установка в chroot.

Запуск

Запустите/включите службу nginx.service.

Страница по умолчанию, доступная по адресу http://127.0.0.1 располагается в /usr/share/nginx/html/index.html.

Настройка

Первые шаги по настройке и использованию nginx описаны в официальном руководстве для начинающих. Вы можете настроить сервер, редактируя файлы в /etc/nginx/; главный файл настроек расположен в /etc/nginx/nginx.conf.

Более подробную информацию можно прочитать на странице Nginx Configuration Examples и в официальной документации.

Приведенные далее примеры покрывают большинство типичных потребностей. Предполагается, что вы используете стандартное место расположения веб-документов (/usr/share/nginx/html). Если это не так, замените путь на свой.

Совет: DigitalOcean предоставляет инструмент для настройки nginx.

Процессы и соединения

Вы должны выбрать подходящее значение для . Этот параметр определяет сколько одновременных соединений сможет принимать nginx и сколько процессоров он сможет при этом использовать. Как правило, это значение устанавливают равным количеству аппаратных потоков в системе. Однако, начиная с версий 1.3.8 и 1.2.5, в качестве значения вы также можете задать , при этом nginx попытается автоматически подобрать оптимальное значение (источник).

Максимальное количество одновременных соединений, которое nginx сможет принимать, вычисляется как .

Запуск под другим пользователем

По умолчанию запускается мастер-процесс nginx от имени root, а он в свою очередь запускает рабочие процессы от имени пользователя . Для запуска рабочих процессов от имени другого пользователя измените значение директивы user в файле :

Если группа не указана, будет использоваться группа, совпадающая с указанным именем пользователя.

Блоки server

Посредством добавления блоков в файл настроек возможно обслуживать сразу несколько доменов одновременно. Эти блоки работают аналогично "VirtualHosts" в Apache. Смотрите также примеры в официальной документации.

В этом примере сервер принимает запросы для двух доменов: и domainname2.dom:

Перезапустите службу nginx.service, чтобы изменения вступили в силу.

Управление блоками server

Для удобства можно поместить разные блоки в разные файлы. Это также позволит включать и отключать отдельные сайты.

Создайте следующие каталоги:

# mkdir /etc/nginx/sites-available
# mkdir /etc/nginx/sites-enabled

Внутри каталога sites-available создайте файл, содержащий один или несколько блоков server:

В файле конце блока добавьте строку :

Чтобы включить сайт, в каталоге создайте символическую ссылку на связанный с ним файл:

# ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/example.conf

А чтобы отключить сайт, удалите её:

# unlink /etc/nginx/sites-enabled/example.conf

Перезапустите службу nginx.service или перезагрузите конфигурацию (reload), чтобы изменения вступили в силу.

TLS

предоставляет поддержку TLS/SSL и установлен по умолчанию на установленных Arch.

Создайте секретный ключ и самоподписанный сертификат. Это подходит для большинства случаев, в которых не требуется CSR:

# cd /etc/nginx/
# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout nginx.key -out nginx.crt -days 1095
# chmod 400 nginx.key
# chmod 444 nginx.crt
Примечание: Опция -days является необязательной, а RSA keysize можно уменьшить до 2048 (по умолчанию).

Если же вам нужно создать CSR, то следуйте данным инструкциям по созданию ключа, вместо приведённых выше:

# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out nginx.key
# chmod 400 nginx.key
# openssl req -new -sha256 -key nginx.key -out nginx.csr
# openssl x509 -req -days 1095 -in nginx.csr -signkey nginx.key -out nginx.crt

В качестве отправкой точки для создания конфигурации TLS в /etc/nginx/nginx.conf можно использовать генератор настроек SSL от Mozilla.

Перезапустите службу nginx, чтобы изменения вступили в силу.

Пользовательские каталоги

Чтобы сделать Apache-подобные адреса вида , указывающие на пользовательские каталоги , используйте подобную конфигурацию. (Примечание: если вы планируете использовать PHP, то связанный с ним location должен стоять первым.)

Подробнее о настройке PHP в nginx смотрите в разделе #Реализация PHP.

Перезапустите службу nginx.service, чтобы изменения вступили в силу.

FastCGI

FastCGI или просто FCGI — это протокол, являющийся интерфейсом между веб-сервером и интерактивными программами. Это модифицированный CGI (Common Gateway Interface), главная цель которого — снизить накладные расходы, связанные со взаимодействием веб сервера и CGI программ, тем самым позволяя серверу обрабатывать большее количество запросов одновременно.

Технология FastCGI встроена в nginx для работы со многими внешними инструментами, например, Perl, PHP и Python.

Реализация PHP

В качестве FastCGI-сервера для PHP рекомендуется использовать PHP-FPM.

Установите пакет и проверьте корректность настроек PHP. Основным конфигурационным файлом PHP-FPM является . Включите и запустите systemd службу .

Настройка nginx

Внутри каждого блока , который обслуживает веб-приложение PHP, должен находиться блок , например:

Если требуется обрабатывать другие расширения наряду с PHP (например .html и .htm):

location ~ [^/]\.(php|html|htm)(/|$) {
    ...
}

Все расширения, обрабатываемые в php-fpm должны быть также явно добавлены в /etc/php/php-fpm.d/www.conf:

security.limit_extensions = .php .html .htm
Совет: Если несколько блоков server используют одну и ту же конфигурацию PHP-FPM, можно вынести общие настройки в отдельный файл для удобства, например php_fastcgi.conf:
/etc/nginx/php_fastcgi.conf
location ~ \.php$ {
    # 404
    try_files $fastcgi_script_name =404;

    # default fastcgi_params
    include fastcgi_params;

    # fastcgi settings
    ...
}

И затем подключать этот файл в тех блоках server, в которых нужна обработка PHP:

/etc/nginx/sites-available/example.conf
server {
    server_name example.com;
    ...

    include /etc/nginx/php_fastcgi.conf;
}
Проверка конфигурации

Перезапустите службы и nginx после изменения настроек, чтобы изменения вступили в силу.

Чтобы проверить работу FastCGI, создайте новый файл .php внутри каталога веб-документов, содержащий:

<?php
  phpinfo();
?>

При открытии файла в браузере должна отобразиться информационная страница с текущими настройками PHP.

Реализация CGI

Эта реализация нужна для CGI-приложений.

fcgiwrap

Установите . Настроить его можно путём редактирования юнита . Включите и запустите .

Несколько рабочих потоков

Если вы хотите породить несколько рабочих потоков, вам рекомендуется использовать , который умеет отслеживать упавшие подпроцессы и перезапускать их. Вам нужно использовать , чтобы создать доменный сокет Unix, так как multiwatch не может обрабатывать сокеты, созданные systemd, однако, fcgiwrap сама по себе не вызывает никаких проблем, если вызывается непосредственно из юнит-файла.

Сделайте замещение файла юнита (и юнита , если он есть), и отредактируйте строку в соответствии с вашими нуждами. В примере показан юнит файл, который использует . Убедитесь, что не включен и не запущен, потому что он будет конфликтовать с этим юнитом:

Выберите подходящий -f 10, чтобы изменить количество порождаемых подпроцессов.

Настройка nginx

В каталоге скопируйте файл в fcgiwrap_params. В файле fcgiwrap_params удалите строки, которые устанавливают и .

Внутри каждого блока CGI-приложения должен находиться вложенный блок :

location ~ \.cgi$ {
     include       fcgiwrap_params;
     fastcgi_param DOCUMENT_ROOT /srv/www/cgi-bin/;
     fastcgi_param SCRIPT_NAME   myscript.cgi;
     fastcgi_pass  unix:/run/fcgiwrap.sock;
}

Сокетом по умолчанию для является .

Вместо параметров и можно использовать более короткую альтернативу . При её использовании не понадобится копировать в fcgiwrap_params и удалять строки and .

Важно: Если используются SCRIPT_NAME и DOCUMENT_ROOT, fcgiwrap будет отклонять любые другие fastcgi_param, установленные в nginx. Вы должны использовать SCRIPT_FILENAME для того, чтобы другие параметры (например, PATH_INFO) могли быть установлены через конфигурацию Nginx. Подробнее на GitHub.

Если вы продолжаете получать ошибку , проверьте, передаёт ли ли ваше CGI-приложение mime-тип содержимого. Для html это должно быть .

Если вы получаете ошибки 403, убедитесь, что CGI-файл доступен для чтения и выполнения пользователю и что каждая родительская папка доступна ему для чтения.

Установка в chroot

Установка nginx в chroot добавляет дополнительный уровень безопасности. Для максимальной безопасности chroot должен включать только файлы, необходимые для запуска сервера nginx, при этом все файлы должны иметь по возможности максимально ограниченные права доступа. Например, как можно больше файлов должно принадлежать пользователю root, а таким каталогам, как должен быть установлен запрет на чтение и запись.

Arch поставляется с пользователем и группой по умолчанию, от имени которых запускается сервер. Измененный корневой каталог будет находиться в .

Существует perl-скрипт для создания chroot-окружения, который доступен в jail.pl gist. Вы можете либо использовать его, либо следовать дальнейшим инструкциям из этой статьи. Скрипт требует прав суперпользователя для работы. Вам нужно будет раскомментировать строку, перед тем, как он сможет выполнять какие-либо изменения.

Создание необходимых устройств

Для nginx нужны , /dev/random и . Чтобы установить их в chroot мы создадим каталог и добавим устройства с помощью mknod. Избегайте монтирования всех устройств в : тогда, даже если chroot будет скомпрометирован, атакующий должен будет выбраться из chroot-окружения чтобы добраться до важных устройств, например .

Совет: Убедитесь, что /src/http примонтирован без опции no-dev
# export JAIL=/srv/http
# mkdir $JAIL/dev
# mknod -m 0666 $JAIL/dev/null c 1 3
# mknod -m 0666 $JAIL/dev/random c 1 8
# mknod -m 0444 $JAIL/dev/urandom c 1 9

Создание необходимых каталогов

Для работы nginx требует определенный набор файлов. Перед тем, как их копировать, создайте для них соответствующие каталоги. Предполагается, что ваш корневой каталог веб-документов nginx находится в .

# mkdir -p $JAIL/etc/nginx/logs
# mkdir -p $JAIL/usr/{lib,bin}
# mkdir -p $JAIL/usr/share/nginx
# mkdir -p $JAIL/var/{log,lib}/nginx
# mkdir -p $JAIL/www/cgi-bin
# mkdir -p $JAIL/{run,tmp}
# cd $JAIL; ln -s usr/lib lib
# cd $JAIL; ln -s usr/lib lib64
# cd $JAIL/usr; ln -s lib lib64

Затем смонтируйте и как tmpfs-ы. Размер должен быть ограничен, чтобы быть уверенным, что атакующий не сможет занять всю доступную RAM.

# mount -t tmpfs none $JAIL/run -o 'noexec,size=1M'
# mount -t tmpfs none $JAIL/tmp -o 'noexec,size=100M'

Для того, чтобы монтирование выполнялось автоматически при загрузке системы, добавьте следующие записи в :

Заполнение chroot

Сначала скопируйте простые файлы.

# cp -r /usr/share/nginx/* $JAIL/usr/share/nginx
# cp -r /usr/share/nginx/html/* $JAIL/www
# cp /usr/bin/nginx $JAIL/usr/bin/
# cp -r /var/lib/nginx $JAIL/var/lib/nginx

Теперь скопируйте нужные библиотеки. Используйте ldd, чтобы отобразить их и скопируйте все файлы в правильное место. Копирование предпочтительнее, чем создание жестких ссылок, потому, что даже если атакующий получит права записи в файлы, они не смогут уничтожить или изменить системные файлы вне chroot-окружения.

Для файлов, находящихся в , вы можете воспользоваться следующей командой:

# cp $(ldd /usr/bin/nginx | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') $JAIL/usr/lib

А для ld-linux-x86-64.so — следующей командой:

# cp /lib64/ld-linux-x86-64.so.2 $JAIL/lib

Копируйте другие необходимые библиотеки и системные файлы.

# cp /usr/lib/libnss_* $JAIL/usr/lib
# cp -rfvL /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf,nginx} $JAIL/etc

Создайте файлы пользователей и групп в chroot-окружении. Таким образом, в chroot-окружении будут доступны только указанные пользователи, и никакая информация о пользователях из основной системы не будет доступна атакующему, получившему доступ в chroot-окружение.

$JAIL/etc/passwd
http:x:33:33:http:/:/bin/false
nobody:x:99:99:nobody:/:/bin/false
# touch $JAIL/etc/shells
# touch $JAIL/run/nginx.pid

Наконец, сделайте права доступа максимально ограниченными. Как можно больше должно принадлежать суперпользователю и быть закрытым для записи.

# chown -R root:root $JAIL/

# chown -R http:http $JAIL/www
# chown -R http:http $JAIL/etc/nginx
# chown -R http:http $JAIL/var/{log,lib}/nginx
# chown http:http $JAIL/run/nginx.pid

# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod -rw
# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod +x
# find $JAIL/etc -gid 0 -uid 0 -type f -print | xargs chmod -x
# find $JAIL/usr/bin -type f -print | xargs chmod ug+rx
# find $JAIL/ -group http -user http -print | xargs chmod o-rwx
# chmod +rw $JAIL/tmp
# chmod +rw $JAIL/run

Если ваш сервер будет принимать входящие соединения на 80 порту (или любому другому порту в диапазоне [1-1023]), дайте исполняемому файлу внутри chroot права на использование этих портов без прав суперпользователя.

# setcap 'cap_net_bind_service=+ep' $JAIL/usr/bin/nginx

Отредактируйте nginx.service для запуска chroot

Сделайте замещение файла юнита nginx.service — тогда обновление nginx не изменит ваш файл .service.

Юнит systemd должен быть настроен так, чтобы запускать nginx в chroot от имени пользователя http и хранить pid-файл в chroot.

Теперь вы можете спокойно удалить nginx, установленный вне chroot.

# pacman -Rsc nginx

Если вы не удалили nginx, установленный вне chroot, проверьте, что работающий процесс nginx — это действительно именно тот, что в находится chroot. Для этого посмотрите, куда указывает символическая ссылка : она должна указывать на , а не на /.

# ps -C nginx | awk '{print $1}' | sed 1d | while read -r PID; do ls -l /proc/$PID/root; done

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

Запуск без привилегий через systemd

Создайте drop-in файл для службы nginx.service и пропишите в нём секцию с опцими и (опционально) , чтобы запустить службу от имени указанного вами непривилегированного пользователя:

Также можно запретить повышение привилегий:

/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
NoNewPrivileges=yes

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

Порт

По умолчанию Linux запрещает не-root процессам слушать порты ниже 1024. Можно использовать порт выше 1024:

Или можно выдать процессу nginx привилегию CAP_NET_BIND_SERVICE, которая позволит ему использовать порты ниже 1024:

/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
CapabilityBoundingSet=
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=
AmbientCapabilities=CAP_NET_BIND_SERVICE

Или можно использовать активацию сокетов systemd. В этом случае systemd будет прослушивать порты и, когда будет установлено соединение, запустит nginx, передав сокет в качестве дескриптора файла. Это означает, что процессу nginx не нужны особые привилегии, так как сокет уже существует на момент запуска. Этот подход опирается на использование внутренней переменной окружения, которую nginx использует для передачи сокетов , и поэтому официально не поддерживается. Вместо установки и переопределите переменную окружения , чтобы сообщить процессу nginx, какие файловые дескрипторы будут передаваться сокетам:

На каждый прослушиваемый порт будет приходиться один сокет, начиная с файлового дескриптора 3, поэтому в данном примере мы говорим nginx ожидать два сокета. Теперь создайте юнит , указав, какие порты прослушивать:

Сокеты будут передаваться в порядке, определённом в этом юните, поэтому порт 80 будет файловым дескриптором 3, а порт 443 — файловым дескриптором 4. Если вы ранее включали или запускали службу nginx.service, вам нужно остановить её и включить вместо неё . При запуске системы nginx не будет запущен, но запустится, когда вы зайдете на сайт в браузере. Благодаря этому можно дополнительно защитить службу; например, во многих случаях вы можете установить PrivateNetwork=True в файле службы, блокируя nginx от внешней сети, поскольку сокета, созданного systemd, достаточно для обслуживания веб-сайта. Обратите внимание, что при этом в журналы службы nginx будет выведено предупреждение:

PID-файл

По умолчанию nginx использует . Нужно будет создать каталог, в котором пользователь будет иметь право записи, и перенастроить запись PID-файла туда. Например, можно использовать systemd-tmpfiles:

Примените изменения:

# systemd-tmpfiles --create

Отредактируйте параметры службы, связанные с PID-файлом:

/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
PIDFile=/run/nginx/nginx.pid
ExecStart=
ExecStart=/usr/bin/nginx -g 'pid /run/nginx/nginx.pid; error_log stderr;'
ExecReload=
ExecReload=/usr/bin/nginx -s reload -g 'pid /run/nginx/nginx.pid;'

/var/lib/nginx/*

Некоторые каталоги в каталоге должны быть инициализированы путём запуска nginx от имени root. Для этого не обязательно запускать весь сервер, nginx сделает это при проверке конфигурации. Так что просто запустите её — и готово.

Права каталогов и файлов журналов

После запуска проверки конфигурации будет создан журнал, принадлежащий root. Удалите журналы в .

Пользователю, от имени которого будет работать служба, nginx нужно выдать разрешение на запись в . Для этого может понадобиться изменить права и/или владельца каталога.

Альтернативный скрипт для systemd

В systemd есть встроенная возможность запуска через chroot. . Для примера используем такие настройки пользователя, группы и pid:

Абсолютный путь к файлу настроек будет .

Указывать стандартный путь к файлу настроек необязательно, nginx по умолчанию использует -c /etc/nginx/nginx.conf, но, возможно, явное прописывание является хорошей идеей.

Также можно запускать только внутри chroot с параметром заданным как (смотрите ) или запустить его до того, как точка монтирования станет эффективной или будет доступен путь systemd (смотрите ).

/etc/systemd/system/nginx.path
[Unit]
Description=nginx (Chroot) path
[Path]
PathExists=/srv/http/site/Public_html
[Install]
WantedBy=default.target

Включите созданный юнит и в юните nginx.service измените строку на .

Параметр в файле юнита позволяет systemd следить за процессом (требуется абсолютный путь). Если это нежелательно, вы можете изменить тип на oneshot и удалить упоминание pid-файла из файла юнита.

Nginx beautifier

— это инструмент командной строки, используемый для улучшения и форматирования конфигурационных файлов nginx.

Более удобное управление заголовками

Nginx имеет довольно неинтуитивную систему управления HTTP-заголовками: они могут быть определены только в одном контексте, любые другие заголовки игнорируются. Чтобы исправить это, можно установить модуль headers-more-nginx.

Установите пакет nginx-mod-headers-more. Модуль будет установлен в каталог .

Чтобы загрузить модуль, добавьте следующее в начало основного конфигурационного файла nginx.

Решение проблем

Ошибка: Страница, которую вы ищете, временно недоступна. Пожалуйста, попробуйте позже. (502 Bad Gateway)

Это из-за того, что сервер FastCGI не запущен или используемый сокет имеет неправильные права доступа.

Попробуйте этот ответ, чтобы исправить 502 ошибку.

В Arch Linux, файлом настройки, упомянутом по ссылке выше, является .

Ошибка: No input file specified

1. Убедитесь, что переменная в содержит путь, который соответствует аргументу root в (обычно ). Если в качестве FastCGI-сервера используется PHP-FPM, можно попробовать добавить в тот блок , который используется для обработки php-файлов.

2. Другой причиной может быть то, что задан неправильный аргумент root в секции location ~ \.php$ в . Убедитесь, что root указывает на ту же директорию, что и в на том же сервере. Либо вы можете просто задать параметр root глобально, не переопределяя его в каких-либо location секциях.

3. Проверьте права доступа: например, пользователь/группа , биты разрешений для каталогов и 644 для файлов. Имейте в виду, что все родительские каталоги тоже должны иметь корректные права доступа. Как массово изменить права всего дерева каталогов, описано в разделе Разрешения и атрибуты файлов#Массовое изменение разрешений.

4. Возможно, у вас не установлена переменная , содержащая полный путь до ваших скриптов. Если конфигурация nginx () правильная, то эта ошибка означает, что php не смог загрузить запрашиваемый скрипт. Часто это просто оказывается ошибкой прав доступа, и вы можете запустить php-cgi с правами root:

# spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/bin/php-cgi

или вам следует создать группу и пользователя для запуска php-cgi:

# groupadd www
# useradd -g www www
# chmod +w /srv/www/nginx/html
# chown -R www:www /srv/www/nginx/html
# spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/bin/php-cgi

5. Если вы используете chroot, убедитесь, что опция в файле имеет корректное значение.

Warning: Could not build optimal types_hash

Если при запуске nginx.service в журнале появляется такое сообщение:

[warn] 18872#18872: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size

то попробуйте увеличить значения этих параметров в блоке :

Cannot assign requested address

Полный текст ошибки в статусе юнита nginx.service:

[emerg] 460#460: bind() to A.B.C.D:443 failed (99: Cannot assign requested address)

Даже если файл юнита nginx настроен на запуск после с помощью systemd, nginx может попытаться прослушивать адрес, который настроен, но ещё не добавлен ни к одному интерфейсу. Убедиться, что проблема именно в этом, можно, попытавшись запустить nginx вручную (тем самым показав, что IP-адрес настроен правильно). Настройка nginx на прослушивание всех адресов решит эту проблему. Если же в вашем случае обязательно требуется прослушивание конкретного адреса, одним из возможных решений является перенастройка systemd.

Чтобы запустить nginx только после того, как все настроенные сетевые устройства будут запущены и получат IP-адреса, добавьте network-online.target к строке в файле nginx.service и запустите/включите .

Смотрите также

gollark: Okay, fine, no casting.
gollark: Right, anonymous individual, you're getting cast into the outer darkness.
gollark: Tell me if you take it or be cast into the outer darkness.
gollark: https://dragcave.net/teleport/81494b3e0a847f281f8f1b0a970a348d3G silver tinsel from 3 tinsels.
gollark: anyone want a 2G xenowyrm of some sort?
This article is issued from Archlinux. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.