В прошлой статье, мы научились создавать сайт используя Hugo. Проблема в том, что наш сайт пока живет только локально в нашем ПК. Как сделать так, чтобы он стал доступен другим пользователям интернета? Давайте разбираться.
Публиковать можно двумя способами. Самый простой – это использовать специальный сервис. Способ посложнее – это арендовать сервер и настроить на нем Nginx. Мы рассмотрим оба способа.
Простой путь подойдет вам, если вы не планируете устанавливать что-то еще. Например, можно установить свои комментарии или счетчик просмотров.
GitLab
Какой бы вы путь не выбрали, вам необходимо сначала зарегистрироваться в GitLab. После регистрации создайте приватный проект.
Теперь у вас есть путь до git репозитория: https://gitlab.com/uPagge/mymeagesite.git
Помните, мы использовали git в нашем проекте. Давайте добавим удаленный репозиторий, который мы только что создали. Для этого зайдите в папку вашего сайта и выполните следующую команду:
git remote add origin git@gitlab.com:uPagge/mymeagesite.git
Тем самым вы связали свой локальный git-репозиторий с удаленным на GitLab.
Теперь необходимо отправить ваш проект в GitLab. Для этого следом выполните команду:
git push --set-upstream origin master
Подсчет объектов: 5, готово.
Delta compression using up to 4 threads.
Сжатие объектов: 100% (4/4), готово.
Запись объектов: 100% (5/5), 969 bytes | 969.00 KiB/s, готово.
Total 5 (delta 0), reused 0 (delta 0)
To gitlab.com:uPagge/mymeagesite.git
* [new branch] master -> master
Ветка «master» отслеживает внешнюю ветку «master» из «origin».
Переходим непосредственно к публикации сайта в интернет.
Публикация через Netlify
Этот вариант подойдет вам, если вы не планируете самостоятельно устанавливать дополнительные сервисы для вашего блога.
Зарегистрируйтесь в Netlify, после чего нажмите кнопку “New Site from Git”.
Выбирайте GitLab.
Выбирайте ваш репозиторий в GitLab.
В следующем пункте все будет установлено автоматически, но вот на всякий случай необходимые настройки.
Нажимаем “Deploy to Site” и немного ждем. В результате мы получаем наш сайт в интернете. Открываем выданный нам адрес и…
Воу, что случилось. Все дело в том, что мы до этого момента не знали, какой домен будет у нашего сайта. И поэтому у нас в config.toml
указан следующий параметр: baseURL = "https://example.com/"
.
Из-за этого у нас неправильно указаны пути к стилям CSS.
Исправим это указав в config.toml
наш домен. После изменения домена необходимо отправить изменения в удаленный репозиторий. Для этого выполните команду:
git commit -m "commit_message"
git push origin master
И все, netlify сам обнаружит изменения и выполнит сборку и повторную публикацию вашего сайта.
Снова открываем наш сайт.
Домен вида nostalgic-goldstine-67b600.netlify.app выглядит не очень красиво, да и запоминается сложно.
Вы можете купить свой красивый домен и привязать его в netlify.
Публикация сайта на VPS
Итак, простой путь это не про вас. Вы хотите больше контроля, тогда арендуйте VPS. Я постарался максимально облегчить вам жизнь, своей инструкцией.
Генерация сайта будет происходить на стороне GitLab, на сервер будет попадать только сгенерированный сайт, то есть папка public
.
Первом делом арендуйте VPS, его также называют VDS. Вы можете выбрать любой, моя рекомендация это VDSina.
Подключаемся к нашему серверу через консоль linux или Putty для windows.
ssh root@188.225.43.153
The authenticity of host '188.225.43.153 (188.225.43.153)' can't be established.
ECDSA key fingerprint is SHA256:sVi8p6f+3pvWbJv/u4rzv5RtUTMcrhCTI9yzVkCXoSI.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '188.225.43.153' (ECDSA) to the list of known hosts.
root@188.225.43.153's password:
Activate the web console with: systemctl enable --now cockpit.socket
Подтверждаем, что хотим добавить сервер в список известных серверов и вводим пароль. Первым делом после входа обновляем систему.
yum update && yum upgrade
Создаем нового пользователя
Создадим нового пользователя и все действия будем делать от его имени.
Команды для CentOS 8, для других дистрибутивов могут быть другие команды.
useradd upagge
passwd upagge
Changing password for user upagge.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
usermod -aG wheel upagge
exit
Проверьте авторизацию через нового пользователя:
ssh upagge@188.225.43.153
Создаем ключи для сервера
Как я уже говорил, мы будем генерировать сайт на стороне GitLab. Для этого нам необходимо будет настроить доставку папки public
на сервер, с помощью GitLab CI.
Чтобы GitLab CI имел возможность войти на наш сервер, надо сгенерировать SSL ключи.
Команда для генерации:
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user_name/.ssh/id_rsa): /home/user_name/.ssh/megasite
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user_name/.ssh/megasite.
Your public key has been saved in /home/user_name/.ssh/megasite.pub.
The key fingerprint is:
SHA256:QjNqmEYk1ncTZcTQyUyM8m+Y2R2txOQCV65Xc08F0Mo user_name@localhost
The key's randomart image is:
+---[RSA 2048]----+
|..o o&=o..o...|
|.o . o =.O.. . .|
| . . B + +o.+ ..|
| . o o + ..=E.o..|
| + o . S.+.o .|
| . . = +.o |
| . |
| |
| |
+----[SHA256]-----+
Не устанавливайте пароль на ключ. Имя ключа можете оставить по умолчанию id_rsa, так как у меня уже есть главный ключ id_rsa, и я не хотел его затирать, я задал новое имя megasite.
Теперь необходимо загрузить наш публичный ключ на сервер, чтобы иметь возможность заходить на него без пароля.
ssh-copy-id -i ~/.ssh/megasite.pub upagge@188.225.43.153
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user_name/.ssh/megasite.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
upagge@188.225.43.153's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'upagge@188.225.43.153'"
and check to make sure that only the key(s) you wanted were added.
Теперь вы можете зайти на свой сервер через ssh ключ без пароля, но главное, что это сможет сделать GitLab.
ssh upagge@188.225.43.153
Настройка GitLab CI/CD
GitLab CI позволит нам генерировать сайт и отправлять его к нам на сервер.
Создайте файл в корне проекта с названием .gitlab-ci.yml
:
image: upagge/hugo-builder:latest
build:
variables:
GIT_SUBMODULE_STRATEGY: recursive
only:
- master
before_script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -p $PORT $HOST >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- hugo --minify
- tar -zcf public.tar.gz ./public
- scp -C -P $PORT -r ./public.tar.gz $USER@$HOST:$SITE_PATH/
- ssh $USER@$HOST -p $PORT "rm -rf $SITE_PATH/public/*"
- ssh $USER@$HOST -p $PORT "cd $SITE_PATH && tar -xf public.tar.gz && rm public.tar.gz"
Перед коммитом и пушем в GitLab необходимо добавить переменные GitLab CI: Settings -> CI/CD -> Variables
SSH_PRIVATE_KEY
- ваш приватный SSH ключ.
Получить его можно командой cat /path_to_private_key
. Пример:
cat ~/.ssh/megasite
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1YEoaZk4EfJCS3f3uq85alhztxVDZ9nG96kOQ8eriud2pamQ
dtl+CO0UOFrytzn2miud2dLx2NUr35Qixto4yw6slGpWMU51wqm3JOYELtKXYfjv
SkY1v...
-----END RSA PRIVATE KEY-----
Скопируйте весь ответ команды.
USER
- пользователь на сервер. В нашем случае upagge.HOST
- IP адрес сервера.PORT
- порт для подключения. Если вы его не меняли, то 22.SITE_PATH
- путь до папки, в которую GitLab поместитpublic
. В моем случае /home/upagge/
Весь блок before_script
отвечает за настройку SSH авторизации.
Разберем построчно блок script
:
- Строка 16 генерирует сайт.
- Строка 17 создает архив из папки
public
. Таким образом сайт быстрее загрузится на сервер. - Строка 18 загружает архив на сервер в папку
SITE_PATH
. - Строка 19 удаляет старую папку
public
на сервере. - Строка 20 распаковывает архив и удаляет сам архив.
Если вы добавили тему для Hugo в качестве git-submodule, то GIT_SUBMODULE_STRATEGY: recursive
загрузит тему за вас.
После добавления переменных выполняем команды commit
и push
.
git add .gitlab-ci.yml
git commit -m 'gitlab ci'
git push
Заходим в проект на GitLab в раздел Pipelines и видим, что все прошло успешно.
Заходим на сервер и проверяем, что папка public
появилась и не пустая:
ls
public
ls public/
404.html article categories en index.html index.xml page series tags theme.js
algolia-logo-light.svg author de fonts index.json modernizr-simple.js robots.txt sitemap.xml theme.css theme.js.LICENSE.txt
Отлично. Теперь при каждом изменений ветки master
наш сайт будет автоматически обновляться на сервере.
Установка docker и docker-compose
Файлы сайта уже у нас на сервере. Чтобы к ним был доступ из интернета, нам нужен Nginx.
Для установки Nginx будем использовать docker и docker-compose. Это необходимо, чтобы в дальнейшем бесплатно получить https для нашего сайта.
У меня есть отдельная заметка с командами для установки docker и docker-compose на CentOS 8. Можете просто копировать команды оттуда.
Настройка записей DNS
Для сайта необходимо доменное имя. Рекомендую REG.RU.
После покупки домена не забудьте добавить ресурсную запись DNS:
- Тип записи: A
- Subdomain: @
- IP Address: ip адрес вашего сервера
И еще одну запись для www:
- Тип записи: A
- Subdomain: www
- IP Address: ip адрес вашего сервера
После добавления записи нужно подождать, пока DNS сервер их обновит. В зависимости от DNS регистратора обновление может занимать от 15 минут до 24 часов. На REG.RU это занимает от 15 до 30 минут.
Настройка конфигурации Nginx
Создадим папку nginx
в папке пользователя. Так, чтобы папка public
лежала рядом.
mkdir nginx
Теперь заполняем конфигурацию. Замените название домена, если домена пока нет, можно использовать IP сервера. Все что надо заменить выделено желтым.
nano nginx/mysite.conf
server {
listen 80;
listen [::]:80;
root /public;
index index.html;
server_name domain_name.com www.domain_name.com;
location / {
try_files $uri $uri/ =404;
}
}
Обратите внимание, что nginx у нас будет работать в контейнере. Поэтому root /public
это путь до папки в контейнере.
Создание файла Docker Compose
Создадим файл docker-compose.yml
рядом с папкой nginx
и public
.
nano docker-compose.yml
version: '3'
services:
nginx:
image: nginx
container_name: nginx
hostname: nginx
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./public:/public:ro
- ./nginx/mysite.conf:/etc/nginx/conf.d/mysite.conf
Обратите внимание на строки 12 и 13. Так задаются относительные пути до папок, если рядом с файлом не будет папок public
и nginx
, то ничего не заработает.
Запускаем командой:
sudo docker-compose up -d
[sudo] password for upagge:
Creating network "upagge_default" with the default driver
Pulling nginx (nginx:)...
latest: Pulling from library/nginx
f7ec5a41d630: Pull complete
aa1efa14b3bf: Pull complete
b78b95af9b17: Pull complete
c7d6bca2b8dc: Pull complete
cf16cd8e71e0: Pull complete
0241c68333ef: Pull complete
Digest: sha256:75a55d33ecc73c2a242450a9f1cc858499d468f077ea942867e662c247b5e412
Status: Downloaded newer image for nginx:latest
Creating nginx ... done
Проверяем, что контейнер успешно запустился командой ps
:
sudo docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80->80/tcp,:::80->80/tcp
Если у вас другой вывод, то проверьте логи командой:
sudo docker-compose logs nginx
Attaching to nginx
nginx | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
nginx | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
Настройка брандмауэра
По умолчанию на CentOS 8 может быть включен брандмауэр, чаще всего это firewalld
.
Если nginx установлен правильно и брандмауэра нет, то по адресу http://ваш_домен
должен открыться ваш сайт.
Если страница не открывается, то необходимо открыть порт 80 для nginx. Запустите следующую команду, чтобы на постоянной основе активировать соединения HTTP для порта 80:
sudo firewall-cmd --permanent --add-service=http
Для применения изменений вам необходимо перезагрузить службу брандмауэра:
sudo firewall-cmd --reload
Теперь сайт должен открываться.
Настраиваем https
У нас статический сайт и https нам в принципе не нужен. Однако, поисковики лояльнее относятся к сайтам доступным по https, да и пользователи уже не доверяют сайтам по http.
Настройка Nginx
Теперь нам нужно изменить конфигурацию nginx. Добавьте строки 14-17. Они нужны для получения сертификата.
server {
listen 80;
listen [::]:80;
root /public;
index index.html;
server_name test.upagge.ru www.test.upagge.ru;
location / {
try_files $uri $uri/ =404;
}
location ~ /.well-known/acme-challenge {
allow all;
root /public;
}
}
Настройка certbot
Также необходимо добавить в docker-compose.yaml
сервис certbot
:
version: '3'
services:
nginx:
image: nginx
container_name: nginx
hostname: nginx
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./public:/public:ro
- ./nginx:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- ./public:/var/www/html
depends_on:
- nginx
command: certonly --webroot -w /var/www/html --email you@email.ru --agree-tos --no-eff-email --staging -d domain_name.com -d www.domain_name.com
volumes:
certbot-etc:
certbot-var:
После добавления определений службы вы можете запустить контейнеры и протестировать запросы сертификата.
sudo docker-compose up -d
Creating volume "upagge_certbot-etc" with default driver
Creating volume "upagge_certbot-var" with default driver
Pulling certbot (certbot/certbot:)...
latest: Pulling from certbot/certbot
339de151aab4: Pull complete
a860e27ad689: Pull complete
910a9a405b4b: Pull complete
bde2ad12a253: Pull complete
584dc3c8e951: Pull complete
ee0b6a5fc80b: Pull complete
3441ac9951cc: Pull complete
4665ef123f62: Pull complete
5bedd499466f: Pull complete
dec3eef9e94a: Pull complete
4f1c29d810f9: Pull complete
5eb6418594da: Pull complete
5da8c5eff620: Pull complete
Digest: sha256:c62b7ca0d8a064a9a260ee331adbe25abb1802ed104abe85a3e02062bbcf9d60
Status: Downloaded newer image for certbot/certbot:latest
Recreating nginx ... done
Creating certbot ... done
Проверяем, что все прошло успешно
sudo docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:80->80/tcp,:::80->80/tcp
Если ваш вывод отличается, проверьте логи. Как проверять nginx вы уже знаете, для certbot аналогичная команда:
sudo docker-compose logs nginx
Успешный запуск выглядит примерно так.
certbot | Cleaning up challenges
certbot | IMPORTANT NOTES:
certbot | - Congratulations! Your certificate and chain have been saved at:
certbot | /etc/letsencrypt/live/test.upagge.ru/fullchain.pem
certbot | Your key file has been saved at:
certbot | /etc/letsencrypt/live/test.upagge.ru/privkey.pem
certbot | Your certificate will expire on 2021-08-07. To obtain a new or
certbot | tweaked version of this certificate in the future, simply run
certbot | certbot again. To non-interactively renew *all* of your
certbot | certificates, run "certbot renew"
certbot exited with code 0
LetEncrypt имеет ограничения на количество запросов, поэтому мы запускали его в тестовом режиме. Теперь, когда вы убедились, что ваш запрос будет выполнен успешно, вы можете изменить определение службы certbot для удаления флага --staging
.
Найдите раздел файла с определением службы certbot и замените флаг --staging
в параметрах command на флаг --force-renewal
, который будет указывать Certbot, что вы хотите запросить новый сертификат с теми же доменами, что и в уже существующем сертификате. Определение службы certbot
должно выглядеть следующим образом:
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- ./public:/var/www/html
depends_on:
- nginx
command: certonly --webroot -w /var/www/html --email you@email.ru --agree-tos --no-eff-email --force-renewal -d domain_name.com -d www.domain_name.com
...
Снова запускаем docker-compose
, чтобы получить рабочие сертификаты:
sudo docker-compose up -d
После получения сертификатов вы можете перейти к изменению конфигурации Nginx для использования SSL.
Активация SSL в нашей конфигурации Nginx будет подразумевать добавление перенаправления HTTP на HTTPS и указание расположения сертификата и ключей SSL. Также нам нужно будет указать нашу группу Diffie-Hellman, которую мы будем использовать для Совершенной прямой секретности.
Поскольку вы будете воссоздавать службу nginx
для включения этих нововведений, сейчас вы можете остановить ее работу:
sudo docker-compose stop nginx
Создание ключа Diffie-Hellman
Далее создадим ключ Diffie-Hellman:
sudo openssl dhparam -out ./nginx/dhparam-2048.pem 2048
Процесс генерации ключа может занять несколько минут.
Изменяем Nginx
Чтобы добавить данные о Diffie-Hellman и SSL в конфигурацию Nginx, первым делом удалите ранее созданный файл конфигурации Nginx:
rm nginx/mysite.conf
Создадим новую версию файла. Обязательно замените test.upagge.ru
на ваше доменное имя:
nano nginx/mysite.conf
server {
listen 80;
listen [::]:80;
server_name test.upagge.ru www.test.upagge.ru;
location ~ /.well-known/acme-challenge {
allow all;
root /public;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name test.upagge.ru www.test.upagge.ru;
root /public;
index index.html;
ssl_certificate /etc/letsencrypt/live/test.upagge.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test.upagge.ru/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparam-2048.pem;
ssl_buffer_size 8k;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri $uri/ =404;
}
}
Резюмирую
Мы разобрались, какими способами можно опубликовать свой Hugo сайт в интернете. Публикация через Netfly подойдет, если вы не планируете разворачивать какие-нибудь дополнительные сервисы для вашего сайта, в этом случае лучше выбрать VPS.