images / Self_hosted_Hugo.png

Esta postagem foi originalmente de www.jaredwolff.com.

Depois de hospedar com o Netlify por alguns anos, decidi voltar para a hospedagem automática. Existem algumas razões para isso, mas o principal raciocínio foi que eu tinha mais controle sobre como as coisas funcionavam.

Nesta postagem, mostrarei meu fluxo de trabalho para implantar meu Hugo site gerado (www.jaredwolff.com) Em vez de usar o que a maioria das pessoas usaria, eu farei tudo isso usando um servidor baseado no FreeBSD Jails. Ademais, mostrarei alguns truques que aprendi ao longo dos anos no redimensionamento de imagens em massa e muito mais.

Vamos lá.

Onde hospedar?

Se você deseja hospedar seu próprio serviço, precisará de um servidor. É aí que entra um fornecedor de VPS como o Digital Ocean ou o Vultr. Sou fã e utilizo o Digital Ocean há algum tempo. Depois de descobrir o Vultr, experimentei a plataforma deles. Nesta publicação, as instruções serão aplicadas apenas ao Vultr.

Para configurar um novo servidor, aqui estão algumas etapas:

  1. Faça o login com uma conta @ Vultr. (Se você não tiver uma, poderá obter um crédito de conta de US $ 100 por 30 dias se usar meu Link de referência. Eu agradeço seu apoio!)

  2. Crie um novo servidor

    images / Screen_Shot_2020-03-27_at_11.08.31_AM.png

  3. Escolha o FreeBSD 12.1. Ao contrário do Digital Ocean, o Vultr suporta apenas o sistema de arquivos UFS. Muitas vezes, essa é a escolha certa. (O ZFS consome muita memória, o que não funcionaria no nosso caso!)

    images / Screen_Shot_2020-03-27_at_11.08.41_AM.png

  4. Certifique-se de importar sua chave pública. Caso contrário, você não poderá usar imediatamente o login sem senha.

    images / Screen_Shot_2020-03-27_at_11.08.50_AM.png

    Você também pode escolher um rótulo e nome de host do servidor.

  5. Hit that blue Implantar agora e vamos colocar esse programa na estrada.

Configurando seu servidor FreeBSD com Bastille

images / bastille.png

Até recentemente, tudo estava funcionando em uma plataforma baseada no Docker usando Exoframe. Foi fácil e quase sem cérebro. A parte infeliz disso é o fato de o Docker dedicar muito a muitos recursos. Ademais, o gerenciamento de arquivos em um contêiner do Docker é tão ou mais trabalhoso do que hospedá-lo nativamente. Ah, e você verificou quanto espaço o Docker tem usado na sua máquina ultimamente? Na minha máquina de desenvolvimento, havia cerca de 19 GB de espaço. 😬

Então, qual é a alternativa?

Cadeias do FreeBSD usando Bastille.

Eu jogo com Bastille há alguns meses. Quanto mais eu o uso, mais faz 100% de sentido.

O Bastille permite que você crie um (agora) cárter portátil, leve e baseado em FreeBSD. Essas cadeias são “contêineres” que praticamente não têm sobrecarga. Não há daemon (o sistema operacional é o “daemon”!). Ademais, as cadeias são seguras em comparação com a lata de worms que o Docker é. Sim, pode ser necessário compilar e portar alguns utilitários. Muitos já são suportados no gerenciador de pacotes do FreeBSD pkg.

Nesta seção, você aprenderá como executar uma cadeia com caddy para que você possa hospedar seu site com segurança.

Vamos manter o ritmo!

Depois de obter o endereço IP do seu servidor, faça o login:

ssh [email protected]

Você deve receber uma mensagem MOTD e um sh pronto. Woo!

FreeBSD 12.1-RELEASE-p2 GENERICWelcome to FreeBSD!...#

Vamos instalar alguns bits importantes usando pkg (Gerenciador de pacotes do FreeBSD)

pkg install restic rsync bastille

Nós estaremos usando restic para backups, rsync para transferir arquivos e bastille para instalação na cadeia.

Você também precisa configurar algumas rotas estáticas no seu pf.conf. Aqui está um exemplo meu:

ext_if="vtnet0"# Caddy relatedcaddy_addr=10.10.2.20set block-policy returnscrub in on $ext_if all fragment reassembleset skip on lotable  persistnat on $ext_if from  to any -> $ext_if# container routesrdr pass inet proto tcp from any to port 80 -> $caddy_addr port 8880rdr pass inet proto tcp from any to port 443 -> $caddy_addr port 4443# Enable dynamic rdr (see below)rdr-anchor "rdr/*"block in allpass out quick modulate stateantispoof for $ext_if inetpass in inet proto tcp from any to any port ssh flags S/SA keep state

Este é um padrão pf.conf arquivo para bastille. Certifique-se de editar caddy_addr para o IP que você escolheu.

Agora vamos iniciar o firewall. Você será expulso do seu ssh sessão:

sysrc pf_enable="YES"service pf start

Então vamos pegar um pouco bastille configuração fora do caminho:

# set up bastille networkingsysrc cloned_interfaces+=lo1sysrc ifconfig_lo1_name="bastille0"service netif cloneup# bootstrap the base jail and start bastillebastille bootstrap 12.1-RELEASE updatesysrc bastille_enable="YES"service bastille start

Isso configurará sua rede e buscará a cadeia base padrão mais recente que você usará mais tarde.

Em seguida, vamos configurar a prisão:

bastille create caddy 12.1-STABLE 10.10.2.20bastille start caddy

Depois instale caddy

#install the binaryfetch https://github.com/caddyserver/caddy/releases/download/v1.0.4/caddy_v1.0.4_freebsd_amd64.tar.gztar xvf caddy_v1.0.4_freebsd_amd64.tar.gz caddybastille cp caddy caddy /usr/local/bin/rm caddy#create the caddy userbastille cmd caddy pw useradd caddy -m -s /usr/sbin/nologin#install ca root filebastille pkg caddy install ca_root_nss

Ao instalar ca_root_nss , pkg terá que inicializar. Aceite os prompts. Quando terminar aqui, vamos para o próximo passo!

Depois que a instalação estiver concluída, também devemos configurar caddy para iniciar na inicialização. A maneira mais fácil de fazer isso é usar este rc.d roteiro.

#!/bin/sh# $FreeBSD: head/net/caddy/files/caddy.in 452063 2017-10-14 12:58:24Z riggs $## PROVIDE: caddy# REQUIRE: LOGIN# KEYWORD: shutdown## Add the following lines to /etc/rc.conf.local or /etc/rc.conf# to enable this service:## caddy_enable (bool):	Set to NO by default.#				Set it to YES to enable caddy.# caddy_user (user):		Set user to run caddy.#				Default is "caddy".# caddy_group (group):	Set group to run caddy.#				Default is "caddy".# caddy_conf (path):		Path to caddy configuration file.#				Default is /usr/local/etc/caddyfile.conf. /etc/rc.subrname=caddyrcvar=caddy_enableload_rc_config $name: ${caddy_enable:="NO"}: ${caddy_user:="caddy"}: ${caddy_group:="caddy"}: ${caddy_conf:="/usr/local/etc/caddyfile.conf"}: ${caddy_log:="/home/caddy/caddy.log"}: ${caddy_env:="CADDYPATH=/home/caddy/"}: ${caddy_https_port:="4443"}: ${caddy_http_port:="8880"}pidfile="/var/run/caddy.pid"procname="/usr/local/bin/caddy"command="/usr/sbin/daemon"command_args="-f -p ${pidfile} /usr/bin/env ${caddy_env} ${procname} -agree -http-port ${caddy_http_port}  -https-port ${caddy_https_port} -conf=${caddy_conf} -log=${caddy_log} ${caddy_args}"extra_commands="reload"start_precmd=caddy_startprecmdreload_cmd=caddy_reloadcmdcaddy_startprecmd(){      if [ ! -e ${pidfile} ]; then              install -o ${caddy_user} -g ${caddy_group} /dev/null ${pidfile};      fi}caddy_reloadcmd(){      kill -s USR1 $(cat ${pidfile})}run_rc_command "$1"

Remova o caddy executável se você ainda não o fez. Em seguida, crie um novo arquivo com vi. Este será o seu rc.d roteiro!

vi caddy

Em seguida, cole o conteúdo do script acima, salve e saia.

Em seguida, verifique se o arquivo é executável usando chmod e copie para o contêiner Caddy.

chmod +x caddybastille cp caddy caddy /usr/local/etc/rc.d/

Finalmente, precisaremos de um Caddyfile. Aqui está um exemplo de um:

stage.jaredwolff.com {  tls [email protected]  log /home/caddy/stage.jaredwolff.com.log  root /var/www/stage.jaredwolff.com/  gzip  log stderr}

log refere-se a este log de acesso específico do site.

root refere-se a onde a raiz public pasta está na sua máquina. No meu caso, é comum /var/www/. Defina seus caminhos e lembre-se deles. Nós precisaremos deles mais tarde!

Para que o Caddy gere certificados para este subdomínio, você precisará definir o tls opção. Um e-mail é tudo o que é necessário.

Para saber mais sobre a estrutura Caddyfile confira a documentação.

Crie um arquivo chamado caddyfile.conf e copie-o para /usr/local/etc/ no seu contêiner Caddy:

vi caddyfile.conf# Paste your caddyfile contents and savebastille cp caddy caddyfile.conf /usr/local/etc/

Agora você deve redirecionar seu DNS para o IP do servidor. Dessa forma, o Caddy pode gerar / buscar os certificados corretos. Então você pode iniciar o Caddy com:

bastille service caddy caddy start

Você pode verificar o log em /usr/home/caddy/caddy.log para garantir que seu domínio seja provisionado corretamente.

Nota: A configuração com certificados SSL é difícil no começo. (Especialmente se você estiver migrando de outro servidor.) Seu site precisará ser desativado um pouco enquanto você altera as configurações de DNS e inicia caddy. (Isso se você estiver usando o padrão caddy 1.0 Você também pode usar o provedor DNS plugins aqui que tornam as coisas um pouco mais fáceis.)

Agora que temos caddy instalado e funcionando, é hora de copiar nossa hugo ativos gerados usando rsync. Vamos para o próximo passo!

Faço construindo e implantando fácil

images / make.png

Passo muito tempo programando o código C e isso significa que gasto muito tempo usando Makefiles. Para muitos make (ou gmake para GNU make) é a desgraça de nossas existências. Para construir e implantar, make facilita a criação de receitas reutilizáveis. Dessa forma, você sabe que pode implantar com confiança sempre.

Meu Makefile pede emprestado aquele que Victoria Drake postou não muito tempo atrás. Mudei um pouco para atender às minhas necessidades. Vamos fazer um tour e ver o que há dentro:

.POSIX:HUGO_VERSION := 0.66.0OPTIMIZED_DIR := optimizedCONTENT_DIR := contentDEST_DIR := publicSERVER := 123.456.789.10USER := user

A primeira seção contém todas as variáveis ​​que eu uso para informar as funções posteriormente sobre o que fazer. Também tem uma referência ao .POSIX alvo. Isso significa que o Makefile será tão portátil entre diferentes versões do make.

Em seguida, criei uma lógica para determinar se estou implantando no palco ou Produção:

# Set the place where it's deployed to.ifdef PRODUCTION$(info Building for production. 🚀)TARGET := wwwelse$(info Building for development. 🚀)BASEURL := --baseURL "https://stage.jaredwolff.com"TARGET := stageendif

Por padrão, as receitas abaixo usarão o fluxo de trabalho de desenvolvimento. Para usar o fluxo de trabalho de produção, você pode chamar make como isso:

PRODUCTION=1 make build

Isso adiciona algum atrito extra ao processo de implantação. É um bom passo, no entanto. Dessa forma, você tem certeza de que a implantação está indo para o lugar certo!

# Full pathDEPLOY_DIR := /usr/local/bastille/jails/caddy/root/path/to/$(TARGET).jaredwolff.com

Usando o TARGET variável acima, defino o caminho para os ativos do meu servidor. Estou usando o Bastille para organizar minhas cadeias, para que o caminho seja mais longo. (sim, longamente) Isso nos permite usar rsync implantar os arquivos com facilidade.

Agora, aqui estão as partes divertidas. Para fazer um redimensionamento em massa completo, estou usando o wildcard funcionalidade do Makefile.

IMAGES := $(wildcard $(CONTENT_DIR)/*/images/*.jpg) $(wildcard $(CONTENT_DIR)/*/images/*.JPG) $(wildcard $(CONTENT_DIR)/*/images/*.jpeg) $(wildcard $(CONTENT_DIR)/*/images/*.png) $(wildcard $(CONTENT_DIR)/*/*/images/*.jpg) $(wildcard $(CONTENT_DIR)/*/*/images/*.jpeg) $(wildcard $(CONTENT_DIR)/*/*/images/*.png) $(wildcard $(CONTENT_DIR)/*/*/images/*.JPG) 

Nesse caso, ele criará uma enorme lista delimitada por espaço de todas as imagens que estão dentro do meu diretório de conteúdo. A maior desvantagem desse método é que ele não é tolerante ao espaço. Uma solução fácil é garantir que todas as minhas fotos não tenham espaços.

Aqui está um comando bash rápido e sujo. Você pode usar o nome para renomear arquivos que possuem espaços e substituí-los por caracteres ‘_’:

for f in * *; do mv "$f" "${f// /_}"; done

Em seguida, renomeamos essas entradas para que o prefixo agora seja o diretório de destino. Isso será útil quando quisermos redimensionar:

OPTIMIZED_IMAGES := $(subst $(CONTENT_DIR)/,$(OPTIMIZED_DIR)/,$(IMAGES))

Agora confira o optimize receita:

.PHONY: optimizeoptimize: build $(OPTIMIZED_IMAGES)@echo "🧂 Optimizing images"rsync -r $(OPTIMIZED_DIR)/ $(DEST_DIR)/du -sh $(CONTENT_DIR)/du -sh $(DEST_DIR)/$(OPTIMIZED_IMAGES):convert -strip -compress JPEG -resize '730>' $(subst $(OPTIMIZED_DIR)/,$(CONTENT_DIR)/,$@) $@

Primeiro chama o build receita e depois também o $(OPTIMIZED_IMAGES) receita. O posterior otimizará a imagem usando o convert comando de Imagemagick. Nesse caso, estou apenas redimensionando arquivos com mais de 730 px de largura. Mude de acordo para poder colher os benefícios de um site otimizado.

Após o redimensionamento, a receita usa rsync para copiar os arquivos do OPTIMIZED_DIR para DEST_DIR.

Se dermos uma olhada no build receita, eu primeiro construindo os ativos. Em seguida, copio as fotos do content dir para optimized dir. O bom é que rsync apenas moverá arquivos que foram alterados. Portanto, não é necessário copiar os arquivos repetidamente e sempre que você criar.

finalmente, o deploy receita.

.PHONY: deploydeploy:@echo rsync to $(DEPLOY_DIR)@rsync -r --del public/ $(USER)@$(SERVER):$(DEPLOY_DIR)/@echo making restic snapshot@scp scripts/backup.sh $(USER)@$(SERVER):/root/backup.sh@ssh $(USER)@$(SERVER) sh /root/backup.sh $(DEPLOY_DIR)@echo "🚀 Site is deployed!"

Você pode ver novamente que estou usando o rsync para sincronizar o conteúdo de public/ para o servidor. Certifique-se de definir o USER , SERVER e DEPLOY_DIR. No meu caso DEPLOY_DIR sai para /usr/local/bastille/jails/caddy/root/var/www/www.jaredwolff.com

Quando você finalmente obtém uma implantação bem-sucedida, pode verificar novamente se tudo está no lugar correto. Então, quando tudo estiver bem, você poderá iniciar seu servidor de caddy usando

bastille service caddy caddy start

deploy também fará algo mais útil aqui. Ele irá implantar meu restic script de backup e execute-o. Vou falar sobre isso mais na seção de backup.

Em suma, aqui está o Makefile completo

.POSIX:HUGO_VERSION := 0.66.0OPTIMIZED_DIR := optimizedCONTENT_DIR := contentDEST_DIR := publicSERVER := 155.138.230.8USER := root# Set the place where it's deployed to.ifdef PRODUCTION$(info Building for production. 🚀)TARGET := wwwelse$(info Building for development. 🚀)BASEURL := --baseURL "https://stage.jaredwolff.com"TARGET := stageendif# Full pathDEPLOY_DIR := /usr/local/bastille/jails/caddy/root/var/www/$(TARGET).jaredwolff.comIMAGES := $(wildcard $(CONTENT_DIR)/*/images/*.jpg) $(wildcard $(CONTENT_DIR)/*/images/*.JPG) $(wildcard $(CONTENT_DIR)/*/images/*.jpeg) $(wildcard $(CONTENT_DIR)/*/images/*.png) $(wildcard $(CONTENT_DIR)/*/*/images/*.jpg) $(wildcard $(CONTENT_DIR)/*/*/images/*.jpeg) $(wildcard $(CONTENT_DIR)/*/*/images/*.png) $(wildcard $(CONTENT_DIR)/*/*/images/*.JPG) OPTIMIZED_IMAGES := $(subst $(CONTENT_DIR)/,$(OPTIMIZED_DIR)/,$(IMAGES)).PHONY: allall: build optimize.PHONY: cleanclean:rm -rf public/rm -rf optimized/.PHONY: serveserve:@hugo serve -D.PHONY: sshssh:@ssh $(USER)@$(SERVER).PHONY: buildbuild:@echo "🍳 Generating site"hugo --gc --minify -d $(DEST_DIR) $(BASEURL)rsync -av --del -f"+ */" -f"- *" $(CONTENT_DIR)/ $(OPTIMIZED_DIR)/.PHONY: optimizeoptimize: build $(OPTIMIZED_IMAGES)@echo "🧂 Optimizing images"rsync -r $(OPTIMIZED_DIR)/ $(DEST_DIR)/du -sh $(CONTENT_DIR)/du -sh $(DEST_DIR)/$(OPTIMIZED_IMAGES):convert -strip -compress JPEG -resize '730>' $(subst $(OPTIMIZED_DIR)/,$(CONTENT_DIR)/,$@) [email protected]: deploydeploy:@echo rsync to $(DEPLOY_DIR)@rsync -r --del public/ $(USER)@$(SERVER):$(DEPLOY_DIR)/@echo making restic snapshot@scp scripts/backup.sh $(USER)@$(SERVER):/root/backup.sh@ssh $(USER)@$(SERVER) sh /root/backup.sh $(DEPLOY_DIR)@echo "🚀 Site is deployed!"

Existem algumas outras pepitas úteis que você pode querer usar. clean, serve e ssh foram muito úteis ao testar e conectar.

No final, você terá um processo de implantação em duas etapas. O primeiro gera seu site com imagens otimizadas. A segunda é a implantação em um servidor para hospedagem estática.

Backup incremental

images / Backup.png

Depois de descobrir Restic Fui informado de como foi útil para todas as minhas necessidades de backup incremental. No caso do meu servidor, estou usando para fazer backup da pasta raiz do meu site. Dessa forma, se eu precisar reverter, posso fazê-lo com alguns passos curtos.

Veja como você pode configurar um local restic repo.

Configurando

A inicialização do repositório é simples. A parte mais importante é garantir que você não perca / esqueça sua senha!

    # restic init -r /root/backups    enter password for new repository:    enter password again:    created restic repository 32e14c7052 at /root/backups    Please note that knowledge of your password is required to access    the repository. Losing your password means that your data is    irrecoverably lost.

Colocou o RESTIC_PASSWORD variável de ambiente para evitar digitar sua senha. Para torná-lo permanente, você terá que colocar export RESTIC_PASSWORD="Your password here!" dentro do .profile arquivo em /root/.

Fazendo backup

Invocando restic sobre SSH é difícil. Então, nossa próxima melhor aposta?

Transfira um script de shell (muito breve) para o servidor e execute-o após uma implantação. Aqui está o conteúdo do que estou usando hoje:

#!/bin/shexport RESTIC_PASSWORD="Your password here!"restic backup $1 -r /root/backups/

Nota: Enquanto eu sento aqui e olho para este script, por motivos de segurança, você pode substituir “Sua senha aqui!” com $ 2, que é o segundo argumento para o script. Dessa forma, você não precisa confirmar / enviar a senha armazenada em um arquivo estático!

Isso primeiro define sua senha de backup. Então corre restic usando o primeiro argumento da linha de comandos como o caminho. Portanto, para executar um backup com este script, seria algo como isto:

./backup.sh /path/to/your/public/folder/

Nota: você precisa inicializar seu restic cópia de segurança antes você começa a fazer backup. Vai vomitar para você de outra forma!

No meu caso, estou colocando os backups incrementais em uma pasta diferente da minha máquina. Dessa forma, eles são facilmente acessíveis e velozes.

Visualizando seus backups

Para visualizar seus backups, você pode executar o seguinte comando:

# restic snapshots -r /root/backups -g paths -center password for repository:repository e140b5e4 opened successfully, password is correctsnapshots for (paths [/usr/local/bastille/jails/caddy/root/var/www/www.jaredwolff.com]):ID        Time                 Host         Tags--------------------------------------------------d3328066  2020-03-10 00:30:58  vultr.guestf3360819  2020-03-10 04:03:03  vultr.guest231dd134  2020-03-10 04:44:00  vultr.guest3c1be26a  2020-03-10 04:56:19  vultr.gueste96c947c  2020-03-10 05:03:00  vultr.guest34c3682a  2020-03-10 14:01:37  vultr.guestfbccdb8c  2020-03-10 14:04:26  vultr.guest9ce11146  2020-03-10 15:38:49  vultr.guest046b3da3  2020-03-10 15:47:06  vultr.guest9c28d4bc  2020-03-10 15:48:25  vultr.guest469dc228  2020-03-10 15:48:54  vultr.guest6f78af72  2020-03-10 17:00:21  vultr.guest29ad17b2  2020-03-10 20:18:23  vultr.guested22ce1f  2020-03-10 20:20:24  vultr.guest9c8c1b03  2020-03-11 13:56:40  vultr.guestb6cfcfec  2020-03-11 14:08:14  vultr.gueste8546005  2020-03-11 14:27:22  vultr.guest49a134fe  2020-03-17 00:47:58  vultr.guestc0beb283  2020-03-18 20:44:52  vultr.guest--------------------------------------------------

Você pode usar esta lista para determinar se você precisa reverter uma implantação.

Restaurando

A restauração de um backup, especialmente em um ambiente ativo, precisa ser rápida. Após visualizar seus backups, você pode restaurar um backup específico usando seu EU IRIA.

restic restore d3328066

Isso restaurará os arquivos de volta ao backup feito em 2020-03-10 00:30:58. Impressionante. Ademais, ele não substituirá todos. Somente aplicará as diferenças entre o estado atual e o estado armazenado.

Conclusão

Cobrimos uma tonelada de terreno neste post. Você aprendeu como:

  • Implante seu próprio servidor usando o Vultr
  • Use Bastille para criar prisões semelhantes a contêineres
  • Configure o Caddy para servir ativos de arquivos estáticos com TLS
  • Implante os arquivos usando um Makefile bastante simples e rsync
  • Faça backup após cada implantação usando restic

No final, temos uma plataforma robusta, segura e simples para hospedar arquivos e serviços estáticos. Fique ligado, pois há mais postagens como essa em breve! Enquanto isso, confira meu outras postagens. Obrigado pela leitura e até a próxima! 👍