Tutorial container Nginx Proxy Manager e WordPress com SSL

Objetivo

Este tutorial tem como objetivo destacar os passos para criar um container WordPress com SSL utilizando um nome de domínio configurado no proxy reverso do container Nginx Proxy Manager.

  • Forma mais simples de garantir suporte SSL ao container do wordpress, não é necessário realizar build para ativar porta 443 interna.
  • Utilizando suporte a HTTP_X_FORWARDED_PROTO, o SSL configurado pelo proxy reverso é redirecionado para dentro do container do WordPress, mesmo que este só tenha a porta 80 habilitada.

Requisitos

  • Se estiver utilizando um servidor caseiro (home lab) seu roteador precisa encaminhar (PORT FOWARD) as portas 80 (http) e 443 (https) para o seu servidor
  • O firewall do seu servidor precisa aceitar acesso na porta 80 e 443 (normalmente são abertas)
  • Garantir que não tenha outro serviço utilizando a porta 80 e 443, senão o container no NPM (Nginx Proxy Manager) não ficará funcional
    • Caso possua o apache instalado, basta executar:
      • sudo service apache2 stop
      • sudo update-rc.d apache2 disable
    • Caso possua o nginx instalado, basta executar:
      • sudo service nginx stop
      • sudo update-rc.d -f nginx disable
  • Ter um nome de domínio configurado e apontado para seu servidor
    • Nesse tutorial vamos usar o nome de domínio site1.com.br como exemplo
  • Ter software docker e docker compose instalados e configurados

Passo a passo para criar containers wordpress com suporte SSL através de proxy reverso do Nginx Proxy Manager

Passo 1: Criar pasta para guardar arquivos

mkdir ~/docker
mkdir ~/docker/nginxproxymanager
mkdir ~/docker/site1.com.br

Passo 2: Criar uma rede para todos os container que utilizarem o proxy reverso

Criar uma rede para os containers conseguirem conversar com o NPM:

docker network create rede_proxy_reverso

Passo 3: Criar arquivo docker compose para nginx proxy manager

cd ~/docker/nginxproxymanager
nano docker-compose.yml

Colar o conteúdo:

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx_proxy
    ports:
      - '80:80'
      - '8081:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    restart: unless-stopped
    networks:
      - rede_proxy_reverso
      - default

  db:
    image: mariadb:latest
    container_name: nginx_proxy_db
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DB}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - ./db_data:/var/lib/mysql
    restart: unless-stopped
    networks:
      - default

networks:
  default:
    name: rede_npm
  rede_proxy_reverso:
    external: true

Passo 5: Criar arquivo .env para nginx proxy manager

cd ~/docker/nginxproxymanager
nano .env

Colar o conteúdo abaixo dentro do arquivo:

MYSQL_USER=nome_usuario_banco_npm
MYSQL_PASSWORD=senha_banco_dados_npm
MYSQL_DB=nome_banco_dados_npm
DOMAIN=nginx.proxy
USER=1000
GROUP=1000

Passo 6: Criar arquivo docker compose para site1.com.br que é um container wordpress

cd ~/docker/site1.com.br
nano docker-compose.yml

Agora precisamos colar o conteúdo abaixo dentro do arquivo:

services:

  db:
    image: mariadb:latest
    container_name: ${DOMAIN}_db
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - ./db_data:/var/lib/mysql
    restart: always
    env_file: .env
    environment:
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_DATABASE=${MYSQL_DB}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
    networks:
      - default

  site1.com.br:
    image: wordpress:latest
    container_name: ${DOMAIN}_web
    env_file:
      - .env
    depends_on:
      - db
    volumes:
      - ./public_html:/var/www/html/
      - ./logs:/var/log/apache2
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    ports:
      - "9080:80"
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=${MYSQL_USER}
      - WORDPRESS_DB_PASSWORD=${MYSQL_PASSWORD}
      - WORDPRESS_DB_NAME=${MYSQL_DB}
      - WORDPRESS_TABLE_PREFIX=${WP_PREFIX}
    extra_hosts:
      - "${DOMAIN}:127.0.1.1"
    entrypoint:
      - /bin/sh
      - -c
      - |
        usermod -u $${USER} www-data
        groupmod -g $${GROUP} www-data
        /usr/local/bin/docker-entrypoint.sh apache2-foreground
    networks:
      - rede_proxy_reverso
      - default

  phpmyadmin:
    container_name: ${DOMAIN}-phpmyadmin
    image: linuxserver/phpmyadmin
    env_file: .env
    environment:
      PMA_HOST: db #nome do container que proverá recursos de banco de dados, neste caso o container chama db
      PMA_PORT: 3306
      MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
      UPLOAD_LIMIT: 64M
      MEMORY_LIMIT: 256M
      MAX_EXECUTION_TIME: 300
    ports:
      - "9081:80"
    networks:
      - default

networks:
  default:
    name: rede_${DOMAIN}
  rede_proxy_reverso:
    external: true

Passo 7: Criar arquivo .env para site1.com.br que é um container wordpress

Precisamos agora criar o arquivo .env para o container wordpress do domínio site1.com.br:

cd ~/docker/site1.com.br
nano .env

Cole o conteúdo abaixo dentro do arquivo:

MYSQL_USER=nome_usuario_banco_site1
MYSQL_PASSWORD=senha_banco_dados_site1
MYSQL_DB=nome_banco_dados_site1
DOMAIN=site1.com.br
WP_PREFIX=wpSITE1_
USER=1000
GROUP=1000

Passo 8: Iniciar os containers

Iniciar o container do Nginx Proxy Manager:

cd ~/docker/nginxproxymanager
docker compose up -d

Iniciar o container wordpress do site1.com.br:

cd ~/docker/site1.com.br
docker compose up -d

Passo 9: Testar funcionamento container wordpress

Configuramos o site1.com.br que é o container wordpress e responder solicitação pela porta 9080 do servidor. Levando em conta que nosso servidor está configurado com o IP 192.168.1.10,  vamos acessar o site com wordpress pelo browser:

http://192.168.1.10:9080

Se tentar acessar o a URL rapidamente, logo em seguida que criou o container, talvez receba mensagem de erro de conexão do banco de dados. O motivo é que o container do mysql demora um pouco para inicializar. Espere mais um pouco e tente acessar a URL novamente.

Se tudo ocorreu corretamente, vai aparecer a tela de configuração inicial do wordpress. Atenção! Não avance com a configuração, o ideal é realizar o processo já com o nome de domínio configurado.

Nginx Proxy Manager - verificando funcionamento container wordpress

Passo 10 – Configurar o Nginx Proxy Manager

Abra o navegador e digite o endereço do servidor juntamente com a porta. Neste exemplo nosso servidor está com endereço IP 192.168.1.10 e porta 8081. Então:

http://192.168.1.10:8081

Agora realize o primeiro login na plataforma:

Login: admin@example.com
Senha: changeme

Nginx Proxy Manager - tela de login

Agora selecione a opção:

Proxy Hosts

Nginx Proxy Manager - ir dashboard proxy hosts

Clique agora no botão:

Add Proxy Host

Nginx Proxy Manager - adicionar proxy hosts

Vamos configurar agora o domínio site1.com.br. Em Domain Names, insira o texto:

site1.com.br

Em Scheme, escolha:

http

Em Foward Hostname / IP, escolha o IP do seu servidor (192.168.1.10), ou o IP de loopback (127.0.0.1) ou o nome do container que possui o wordpress instalado, neste caso:

site1.com.br

Em porta, vamos escolher a porta interna do container. Como temos uma rede dedicada para o proxy reverso (rede_proxy_reverso), o Nginx Proxy Manager consegue conversar pela rede interna compartilhada, não sendo nem mesmo necessário expor a porta do container. Caso não tenha a rede criada, ou vai utilizar o endereço IP, então precisa colocar a porta externa do container (9080). Então vamos escolher a porta:

80

Podemos também habilitar as opções:

Block Common Exploits
Websockets Support

Nginx Proxy Manager - configuração do domínio

Nesta mesma tela, temos alguma opções no menu superior:

Details | Custom locations | SSL | Advanced

Vamos solicitar o certificado SSL, então precisamos selecionar a aba:

SSL

Selecione agora a opção:

Request a new SSL Certificate with Let's Encrypt

Nginx Proxy Manager - solicitar certificado SSL

Caminhe agora para a aba:

Advanced

Cole o seguinte texto:

proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Tudo pronto e configurado. Basta clicar no botão:

Save

Nginx Proxy Manager - configuração do domínio - salvar configurações

Nginx Proxy Manager - domínio configurado

Passo 11: Testar funcionamento

As principais configurações estão prontas. Acesse agora o nome de domínio escolhido pelo browser, no caso deste exemplo:

https://site1.com.br

Caso as configurações tenham sido realizadas corretamente, você irá se deparar com a tela de instalação do wordpress. Pode serguir com a instalação normalmente.

Nginx Proxy Manager - proxy reverso configurado - pronto para instalar wordpress

Passo 12: Resumo de configurações

Um breve resumo das configurações criadas:

Container Nginx Proxy Manager (NPM)

Portas expostas: 80, 443 e 8081
Porta da interface web do NPM: 8081

Container WordPress para o site1.com.br

Portas expostas: 9080 e 9081
Porta site wordpress: 9080
Porta interface phpmyadmin: 9081

IP de exemplo do servidor: 192.168.1.10

Para acessar a interface do NPM: http:192.168.1.10:8081
Para acessar o website pelo ip: http://192.168.1.10:9080
Para acessar a interface do Phpmyadmin: http://192.168.1.10:9081
Para acessar o website criado: https://site1.com.br

Conclusão

O setup do container do NPM + WordPress não é trivial, há pequenos detalhes diante a rede compartilhada entre o proxy reverso e o container do wordpress que influencia na porta a ser utilizada: usualmente pensamos na porta exposta no container, mas a forma mais segura é a porta interna. Utilizar o nome do container (site1.com.br) como “Foward Hostname” dentro do NPM também é um setup que utiliza as vantagens do DNS interno do docker para simplificar a comunicação entre containers. Estas configurações não são triviais para aqueles que estão começando a utilizar o docker e podem causar problemas no setup.

Qualquer dúvida ou sugestão no setup acima, basta entrar em contato pela área de comentários! Feedback é sempre bem vindo!